我的考试怎么了

hivapdat  于 2021-06-21  发布在  Mysql
关注(0)|答案(0)|浏览(202)

到目前为止,对于一个有点奇怪的sql查询,我有两个简单的测试。有两件事我不明白。我的第一个测试没有插入任何数据并运行查询,我希望 if (reader.HasRows) 返回false(确实如此),并且它正确地返回0。第二个测试我插入2条记录,一条是“付费”的,另一条不是(一秒钟后会更有意义)。我只希望看到付款行的总和,但什么也得不到。问题是它是一个对时间敏感的查询,会改变时区。我不知道为什么会这样,但我不能改变这个事实。因为这和工作有关,我得改变一下。易趣模拟器听起来是个很好的例子。
在mysql中创建一个简单的表

CREATE TABLE `order` (
  `id` int(11) unsigned NOT NULL,
  `Total` decimal(8,2) DEFAULT NULL,
  `OrderDate` datetime(6) DEFAULT NULL,
  `Paid` tinyint(3) unsigned NOT NULL,
  `Deleted` tinyint(3) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_UNIQUE` (`id`),
);

现在用nunit做两个简单的测试

[TestFixture]
public class DbAccountingStatisticsTests
{
    private readonly DateTime TodayStartOrDay = DateTime.Today;
    private readonly DateTime TodayEndOfDay = DateTime.Today.AddDays(1).AddTicks(-1);
    private LoggingAssert _logging;
    private DeferredMultiTableDatabaseActions _dbActions;
    private static readonly TimeZoneInfo Pst = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
    private static readonly TimeZoneInfo Est = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

    [SetUp]
    public void Setup()
    {
        _logging = LoggingAssert.Setup();
        _dbActions = new DeferredMultiTableDatabaseActions();
    }

    [TearDown]
    public void TearDown()
    {
        _dbActions.SubmitChanges();
        _logging.FailIfAnyLoggedErrors();
    }

    [Test]
    public void WithZeroShippedOrders()
    {
        var db = new DbAccountingStatistics();

        var stats = db.GetOrderStats(
            TimeZoneInfo.ConvertTime(TodayStartOrDay, Pst),
            TimeZoneInfo.ConvertTime(TodayEndOfDay, Pst)
        );

        Assert.That(stats.NumberofOrders, Is.Zero);
        Assert.That(stats.TotalOrders, Is.Zero);
    }

    [Test]
    public void NonPaidOrdersNotIncluded()
    {
        AddOrder(orderTotal: 100, paid: false);
        AddOrder(orderTotal: 100, paid: true);
        var db = new DbAccountingStatistics();

        var stats = db.GetOrderStats(
            TimeZoneInfo.ConvertTime(TodayStartOrDay, Est),
            TimeZoneInfo.ConvertTime(TodayEndOfDay, Est)
        );

        Assert.That(stats.NumberofOrders, Is.EqualTo(1));
        Assert.That(stats.TotalOrders, Is.EqualTo(100));
    }

    private void AddOrder(decimal orderTotal, bool paid)
    {
        var db = new DbOrder();
        var id = db.Insert(new PocoOrder
        {
            Paid = paid,
            Total = orderTotal,
            OrderDate = DateTime.Today//TimeZoneInfo.ConvertTime(DateTime.Today, Est)
        });
        _logging.FailIfAnyLoggedErrors();

        _dbActions.AddSimpleChange($"delete from order where id = {id}");
    }
}

现在被测试的类和给我带来麻烦的sql

public class DbAccountingStatistics
{
    private readonly DeferredMultiTableDatabaseActions _dataAdapter = new DeferredMultiTableDatabaseActions();

    private const string SqlGetOrderStats =
        "SELECT count(id) as orderNum, sum(total) as Total " +
        "FROM order " +
        "WHERE Date(CONVERT_TZ(OrderDate,'US/Eastern','US/Pacific')) >= @STARTDATE " +
        "AND Date(CONVERT_TZ(OrderDate,'US/Eastern','US/Pacific')) <= @ENDDATE " +
        "AND Deleted = 0 and paid = 1";

    public PocoAccountingStatistics GetOrderStats(DateTime startDate, DateTime endDate)
    {
        var stats = new PocoAccountingStatistics();
        _dataAdapter.AddDeferredAction(new DeferredAction<PocoAccountingStatistics>
        {
            Sql = SqlGetOrderStats,
            SqlParameters = new Dictionary<string, object>
            {
                {"@STARTDATE", startDate},
                {"@ENDDATE", endDate},
            },
            ParseAction = FillOrderStats
        });
        _dataAdapter.Fill(stats);
        return stats;
    }

    private void FillOrderStats(PocoAccountingStatistics stats, IDataRecord record)
    {
        var orderCountOrdinal = record.GetOrdinal("orderNum");
        var totalOrdinal = record.GetOrdinal("Total");

        stats.NumberofOrders = (long)record[orderCountOrdinal];
        stats.TotalOrders = record.IsDBNull(totalOrdinal)? 0 : record.GetDecimal(totalOrdinal);
    }
}
public class PocoAccountingStatistics
{
    public long NumberofOrders { get; set; }
    public decimal TotalOrders { get; set; }
}
public class DeferredAction
{
    public string Sql { get; set; }
    public Dictionary<string, object> SqlParameters { get; set; }
}

public class DeferredAction<T> : DeferredAction
{
    public Action<T, IDataRecord> ParseAction { get; set; }
}

public class DeferredMultiTableDatabaseActions
{
    private static readonly Logger logger = LogManager.GetLogger(nameof(DeferredMultiTableDatabaseActions));
    private readonly List<DeferredAction> _deferredActions = new List<DeferredAction>();

    public void AddSimpleChange(string sql)
    {
        _deferredActions.Add(new DeferredAction
        {
            Sql = sql,
        });
    }

    public void AddDeferredAction(DeferredAction deferredAction)
    {
        _deferredActions.Add(deferredAction);
    }

    public void SubmitChanges()
    {
        using (var connection = new BfConnection().DbConnection)
        {
            var db = new Database(connection);
            connection.Open();
            foreach (var clown in _deferredActions)
            {
                using (var command = db.GetCommand(clown.Sql))
                {
                    var rowsAffected = db.ExecuteNonQuery(command);
                    if(rowsAffected < 1)
                        logger.Error($"Expected atleast 1 rows to be affected for statment '{clown.Sql}'");
                }
            }
        }
    }

    public void Fill<T>(T poco)
    {
        using (var connection = new BfConnection().DbConnection)
        {
            var db = new Database(connection);
            connection.Open();
            foreach (var deferredAction in _deferredActions)
            {
                using (var command = db.GetCommand(deferredAction.Sql))
                {
                    foreach (var parameter in deferredAction.SqlParameters)
                        AddParameter(command, parameter.Key, parameter.Value);

                    using (var reader = db.ExecuteReader(command))
                    {
                        if (!reader.HasRows)
                            continue;

                        if (reader.Read())
                            ((DeferredAction<T>) deferredAction).ParseAction(poco, reader);
                    }
                }
            }
        }
    }

    private static void AddParameter(DbCommand command, string name, object value)
    {
        var parameter = command.CreateParameter();
        parameter.ParameterName = name;
        parameter.Value = value;
        command.Parameters.Add(parameter);
    }
}

我第一次做这个测试的时候 DbNull 因为我的时区没有在本地设置,所以我去了mysql的网站,得到了这个设置。然后我研究了 Convert_TZ 所有的一切都在改变 OrderDate 从est到pst并与我的两个参数进行比较。在测试中,我将日期插入为pst、est和我的当前时间(cst)。我也改变了测试转换时间和不转换时间。每次我得到0表示总数和计数。我不明白为什么 HasRows 如果where子句与不插入任何内容相比是错误的,则在插入两条记录时为true HasRows 返回false。我已经和它斗争了几个小时,即使在睡觉后,我仍然不能找出什么是错的。

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题