LINQ To Entities,null导航属性

时间:2014-05-28 15:32:54

标签: asp.net-mvc entity-framework asp.net-mvc-4 linq-to-entities

道歉,如果这是重复的,或者我只需要RTFM,但我找不到完全回答我的问题的帖子。我觉得我正在重新发明轮子,必须有一个更好的方法。 MVC4,实体框架5.我正在使用LINQ将我的域中的实体列表投影到视图模型列表中,并在导航属性指向单个相关实体的情况下遇到NULL引用异常;对于导航属性而言,这些属性是一个深度的集合;然后对于那些可能存在导航属性的人来说,导航属性本身具有导航属性(即,可能有两个级别)。

当我指向实际数据库时似乎工作;我相信这是因为我的配置启用了延迟加载;但是当我编写单元测试时,我得到了NULL引用异常。我有一个解决方案,但有一点代码味道。我想找到一种适用于这两种情况的更清洁的解决方案。

请考虑以下代码:

var theList = DomainContext.MyParentEntities.Select(g => new SomeViewModelForAList {

        SomeStringProperty = g.SingleRelatedEntity.Name,
        SomeIntProperty = 
            g.EntitiesFromSomeOtherTable.Count(x => !x.IsDeleted),
        SomeOtherIntProperty =
            g.YetAnotherRelatedEntity.YetMoreChildren.Count(x => !x.IsDeleted)

}).ToList();

现在,与MyParentEntities实例相关的以下任何实体都可能为NULL:“SingleRelatedEntity”,“EntitiesFromSomeOtherTable”,“YetAnotherRelatedEntity”和/或“YetMoreChildren”。任何这些都可能引发异常。

我可以编写各种NULL合并代码,但是看起来多余且难看。我也看过这里描述的编写扩展方法(尽管Jimmy的帖子看起来有点陈旧,现在可能有更好的方法):

http://lostechies.com/jimmybogard/2009/12/08/linq-query-operators-and-null-lists/

扩展方法的思想是有效的,该技术可以适用于使用泛型的单个相关实体;这是我尝试这样做的:

    public static IEnumerable<TSource> NullsToEmpty<TSource>(this IEnumerable<TSource> source)
    {
        return source ?? Enumerable.Empty<TSource>();
    }

    // same idea here

    public static T NullToEmpty<T>(this T theEntity) where T : EntityBase, new()
    {
        var retVal = new T();
        if (theEntity == null)
        {
            retVal.Name = "";
        }
        else
        {
            retVal = theEntity;    
        }

        return retVal;
    }

然后代码变为:

var theList = DomainContext.MyParentEntities.Select(g => new SomeViewModelForAList {

        SomeStringProperty = g.SingleRelatedEntity.NullToEmpty().Name,
        SomeIntProperty = 
            g.EntitiesFromSomeOtherTable.NullsToEmpty().Count(x => !x.IsDeleted),
        SomeOtherIntProperty =
            g.YetAnotherRelatedEntity.NullToEmpty().
            YetMoreChildren.NullsToEmpty().Count(x => !x.IsDeleted)

}).ToList();

这再次起作用,但也觉得它很丑陋和重复。任何建议赞赏。谢谢,-dB

1 个答案:

答案 0 :(得分:0)

我做了一些额外的观察。有很多问题:

  • 除非您进行集成和/或端到端测试,否则您无法轻松单元测试实体框架,如Ladislov此处及其他地方所述:

Is UnitOfWork and GenericRepository Pattern redundant In EF 4.1 code first?

  • 这是一个让Linq查询正确的问题,这样就不会往返数据库,避免N + 1问题,抓住整个对象图等(即需要集成和单元测试才能确保你做对了

  • (至少在我的情况下),NULL在生产中不是问题,因为EF转换为检查IF EXISTS的SQL;因此我不需要“DefaultIfEmpty()”,例如:

http://www.progware.org/Blog/post/Left-Outer-Join-in-LINQ-to-Entities-%28for-Entity-Framework-4%29.aspx

  • 在我的单元测试中,我通过返回(对于空集)一个新的空集合来模拟EF的行为(因此避免使用NullToEmpty技术,无论如何LINQ to Entities都无法解释)