C# Linq:加入还是不加入(加入还是关系,哪种方式更好)

C# Linq:加入还是不加入(加入还是关系,哪种方式更好),c#,linq-to-sql,join,foreign-key-relationship,C#,Linq To Sql,Join,Foreign Key Relationship,我已经编写了相当多的代码,这些代码仅通过在数据库中使用外键就使用了提供给我的Linq2Sql表关系。但是,事实证明,为我的单元测试模拟数据有点费劲。我必须手动设置测试线束中的任何关系 因此,我想知道,编写Linq连接而不是依赖关系是否会使我的代码更易于测试,性能也可能更高 var query = from orderItem in data.OrderItems select new {

我已经编写了相当多的代码,这些代码仅通过在数据库中使用外键就使用了提供给我的Linq2Sql表关系。但是,事实证明,为我的单元测试模拟数据有点费劲。我必须手动设置测试线束中的任何关系

因此,我想知道,编写Linq连接而不是依赖关系是否会使我的代码更易于测试,性能也可能更高

        var query =
            from orderItem in data.OrderItems
            select new
            {
                orderItem.Order.Reference,
                orderItem.SKU,
                orderItem.Quantity,
            };

        Console.WriteLine("Relationship Method");
        query.ToList().ForEach(x => Console.WriteLine(string.Format("Reference = {0}, {1} x {2}", x.Reference, x.Quantity, x.SKU)));

        var query2 =
            from orderItem in data.OrderItems
            join order in data.Orders
                on orderItem.OrderID equals order.OrderID
            select new
            {
                order.Reference,
                orderItem.SKU,
                orderItem.Quantity,
            };

        Console.WriteLine();
        Console.WriteLine("Join Method");
        query2.ToList().ForEach(x => Console.WriteLine(string.Format("Reference = {0}, {1} x {2}", x.Reference, x.Quantity, x.SKU)));

上面的两个查询都给出了相同的结果,但在性能和可测试性方面是否一个比另一个好?

在性能方面,两个查询的计算结果都是相同的SQL(Scott Guthrie对如何查看LINQ查询生成的SQL有自己的见解)。我不认为这两个选项本质上比另一个更“可测试”。但是,我更喜欢使用外键和关系,因为当使用SQL Metal时,它可以让您非常快速地知道您的数据库具有适当的键。

您在测试什么?Linq对SQL读取数据的能力有什么影响?一般认为,LINQtoSQL是数据库上的一层薄薄的外衣,LINQtoSQL代码本身被认为是“原始的”,因此不需要进行测试


我非常不赞成以这种方式使您的代码复杂化,这样您就可以模拟LINQtoSQLDBML。如果您想测试您的业务逻辑,最好只将测试数据库连接到DBML(datacontext有一个构造函数重载,允许您这样做),并使用数据库事务测试数据交互。这样,您可以回滚事务以撤消对数据库的更改,使测试数据库保持其原始状态。

我认为这两种方法在性能或可测试性方面都没有优势。第一种形式更容易阅读,所以我个人同意。不过这是一个主观问题


在我看来,您的问题在于能够以简单的方式设置数据,并且外键值和实体引用保持一致。我认为这不是一件容易解决的事情。您可以编写某种框架,创建对象代理,并使用实体元数据拦截FK和相关实体属性设置器,以便同步它们,但在您知道之前,您已经实现了内存中的数据库

有趣的是,我最近一直在考虑从单元测试的角度来看,与数据库隔离是一件好事。然而,我接受你的观点,从一个实用的角度来看,仅仅在数据库上运行要容易得多。我的纯粹主义者想称之为集成测试。同意,这实际上是一个集成测试,而且创建数据库的速度要慢得多。我有一个模拟Linq2Sql存储库,它使用我正在“注入”对象的通用列表来代替数据库中的记录。我正在努力解决的是如何轻松地重新创建POCO对象(如果您可以调用Linq2Sql生成的类!)以及使用FKs获得的所有隐含关系。我最近开始使用EF,它更容易编写集成测试。我问这个问题的时候写的代码很好,但是事情已经开始了。我已经形成了你在回答中表达的相同观点,我所有的EF测试都是集成测试。我有一个数据层,其中只包含数据访问代码和一些linq查询,这些查询只通过使用实际数据库的集成测试进行测试。.ToList().ForEach()我也更喜欢使用FKs,但我说的是模拟我的Linq2Sql存储库,这样我就可以对我正在进行的任何复杂查询进行单元测试,也可以对任何周围的逻辑进行单元测试。也许我在使代码可测试性方面遗漏了一个技巧,我只是在创建dbml时使用VisualStudio中生成的代码。SQLMetal是否使类更容易模仿(因此也更容易测试)?SQLMetal将为您提供真正的POCO类,而不是像DBML那样将所有内容隐藏在设计器下。然而,我不认为这能为您节省太多,因为您担心测试中特定实例之间的关系,而不仅仅是结构。这正是我面临的问题,您是对的,构建某种框架来“连接”是一项艰巨的任务所有relationshipsI都已开始使用moq框架,并坚持使用查询语法和显式联接。这对我来说现在工作得很好,允许我对所有业务逻辑(包括linq查询)进行测试