C# 使Linq导航属性对开发人员更加明显

C# 使Linq导航属性对开发人员更加明显,c#,entity-framework,linq,linq-to-sql,linq-to-entities,C#,Entity Framework,Linq,Linq To Sql,Linq To Entities,在我们的代码库中,一个常见的错误是,开发人员编写的循环会在不知不觉中命中实体框架对象中的延迟加载导航属性,从而在循环的每次迭代中触发DB调用。我想知道是否可以使用任何VisualStudio扩展或巧妙的技巧使自动生成的EF对象中的属性实际上是一个导航属性变得更加明显,这样开发人员就更容易注意使用。有什么建议吗?以下是一些想法: 我更喜欢保持域对象最小,所有属性都是列或导航属性。除了解决您描述的问题之外,这使消费者非常清楚哪些属性可以用于LINQ查询(这对复杂属性没有帮助,而这些属性不是导航属性

在我们的代码库中,一个常见的错误是,开发人员编写的循环会在不知不觉中命中实体框架对象中的延迟加载导航属性,从而在循环的每次迭代中触发DB调用。我想知道是否可以使用任何VisualStudio扩展或巧妙的技巧使自动生成的EF对象中的属性实际上是一个导航属性变得更加明显,这样开发人员就更容易注意使用。有什么建议吗?

以下是一些想法:

  • 我更喜欢保持域对象最小,所有属性都是列或导航属性。除了解决您描述的问题之外,这使消费者非常清楚哪些属性可以用于LINQ查询(这对复杂属性没有帮助,而这些属性不是导航属性)
  • 尽早关闭您的工作单元:

//而不是
使用(var work=new MyDbContext())
{
var orders=work.orders.Where(…).ToList();
foreach(订单中的var订单)
{
//在此发出额外查询
Console.WriteLine(order.Customer.Name);
}
}

<代码> /考虑 列出订单; 使用(var work=new MyDbContext()) { orders=work.orders.Where(…).ToList(); } foreach(订单中的var订单) { //现在这一行抛出一个异常,因此开发人员 //将返回并添加.Include()语句 //只是默默地创建缓慢的代码 Console.WriteLine(order.Customer.Name); }

  • 考虑关闭延迟加载。这可以在上下文级别上完成,也可以在单个属性级别上完成,只需将属性设置为非虚拟属性即可。虽然延迟加载很方便,但它可能是一个性能陷阱,对于代码审阅者来说非常不方便,需要额外检查

  • 考虑在您的测试环境中使用一个用于查找惰性负载查询(它们非常独特)并记录问题的日志

  • 让人们在开发时练习使用SqlServer Profiler或on。这使得在发出过多查询时很容易发现

  • 使用Roslyn,您可能会编写一个静态分析代码并在引用这些属性以调用它们时显示一些诊断


谢谢您的想法。DbInterceptor看起来可能是捕捉这些错误的好方法。工作单元方法可能更好。我会调查两者的。

    // instead of
    using (var work = new MyDbContext())
    {
        var orders = work.Orders.Where(...).ToList();
        foreach (var order in orders)
        {
            // extra queries issued here
            Console.WriteLine(order.Customer.Name);
        }
    }

// consider
List<Order> orders;
using (var work = new MyDbContext())
{
    orders = work.Orders.Where(...).ToList();
}

foreach (var order in orders)
{
    // now this line throws an exception, so the developer
    // will go back and add the .Include() statement instead
    // of just silently creating slow code
    Console.WriteLine(order.Customer.Name);
}