道歉,如果这是重复的,或者我只需要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
答案 0 :(得分:0)
我做了一些额外的观察。有很多问题:
Is UnitOfWork and GenericRepository Pattern redundant In EF 4.1 code first?
这是一个让Linq查询正确的问题,这样就不会往返数据库,避免N + 1问题,抓住整个对象图等(即需要集成和单元测试才能确保你做对了
(至少在我的情况下),NULL在生产中不是问题,因为EF转换为检查IF EXISTS的SQL;因此我不需要“DefaultIfEmpty()”,例如: