Linq:加入或不加入(这是更好的方式,加入或关系)
我已经编写了相当多的代码,这些代码使用通过在数据库上拥有外键而提供给我的 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)));
上面的两个查询都给了我相同的结果,但在性能和可测试性方面,一个比另一个更好吗?
I have written quite a bit of code which uses the Linq2Sql table relationships provided to me just by having foreign keys on my database. But, this is proving to be a bit laborious to mock data for my unit tests. I have to manually set up any relationships in my test harness.
So, I am wondering if writing Linq joins rather than relying on the relationships would give me more easily testable and possibly more performant code.
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)));
Both queries above give me the same result, but is one better than the other in terms of performance and in terms of testability?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
你在测试什么? Linq to SQL读取数据的能力?通常认为,linq to sql 是数据库上的一层薄薄的饰面,linq to sql 代码本身被认为是“原始的”,因此不需要进行测试。
我非常不赞成以这种方式使代码复杂化,这样您就可以模拟 linq to sql DBML。如果您想测试业务逻辑,最好将测试数据库连接到 DBML(数据上下文的构造函数重载允许您执行此操作)并使用数据库事务来测试数据交互。这样,您可以回滚事务以撤消对数据库的更改,使测试数据库保持其原始状态。
What are you testing? Linq to SQL's ability to read data? It is generally assumed that, linq to sql being a thin veneer over a database, that the linq to sql code itself is considered "pristine," and therefore doesn't need to be tested.
I am hugely not in favor of complicating your code in this way, just so that you can mock out the linq to sql DBML. If you want to test your business logic, it is far better to just hook up a test database to the DBML (there is a constructor overload for the datacontext that allows you to do this) and use database transactions to test your data interactions. That way, you can roll the transaction back to undo the changes to the database, leaving the test database in its original state.
在性能方面,两个查询将评估为相同的 SQL(Scott Guthrie 有一个 关于如何查看 LINQ 查询生成的 SQL 的博客文章)。我不认为这两种选择本质上比另一种更“可测试”。但是,我更喜欢使用外键和关系,因为使用 SQL Metal 时,它可以让您快速知道您的数据库具有适当的键。
In terms of performance, both queries will evaluate to the same SQL (Scott Guthrie has a blog post on how to view the SQL generated by LINQ queries). I don't think that either option is inherently more "testable" than the other. However, I prefer to use the foreign keys and relationships because when using SQL Metal it lets you know really quickly that your database has the appropriate keys.
我认为这两种方法在性能或可测试性方面都没有优势。第一种形式更容易阅读,所以我个人会选择这种形式。但这是一个主观问题。
在我看来,您的问题在于能够以简单的方式设置数据,并使外键值和实体引用保持一致。我认为这不是一件容易解决的事情。您可以编写某种框架来创建对象代理并使用实体元数据来拦截 FK 和相关实体属性设置器以便同步它们,但在您意识到之前,您将实现一个内存数据库!
I don't think either approach has an advantage in either performance or testability. The first form is easier to read though, and so I would personally go with that. It's a subjective matter though.
It seems to me that your problem lies with being able to setup your data in an easy way, and have the foreign key values and entity references remain consistent. I don't think that's an easy thing to solve. You could write some sort of framework which creates object proxies and uses the entity metadata to intercept FK and related entity property setters in order to sync them up, but before you know it, you'll have implemented an in-memory database!