在logging上的null上调用MAX的entity framework

当在一个IQueryable上调用Max()并且有零个logging时,我得到下面的exception。

强制转换types“Int32”失败,因为物化值为空。 结果types的generics参数或查询必须使用可为空的types。

var version = ctx.Entries .Where(e => e.Competition.CompetitionId == storeCompetition.CompetitionId) .Max(e => e.Version); 

现在我明白为什么发生这种情况我的问题是如果表可以是空的,最好的办法是如何做到这一点。 下面的代码工作和解决这个问题,但它的非常丑陋的是没有MaxOrDefault()概念?

 int? version = ctx.Entries .Where(e => e.Competition.CompetitionId == storeCompetition.CompetitionId) .Select(e => (int?)e.Version) .Max(); 

是的,在LINQ to Entities查询中,推荐使用T的Nullable来处理这个问题。 拥有正确签名的MaxOrDefault()方法听起来像是一个有趣的想法,但是对于每个呈现此问题的方法,您只需要一个额外的版本,而这个方法不会很好地扩展。

这是CLR工作方式与数据库服务器实际工作方式之间的很多不匹配之一。 Max()方法的签名是这样定义的,因为结果types和CLR上的inputtypes是完全一样的。 但在数据库服务器上,结果可能为空。 出于这个原因,你需要投入input(尽pipe取决于你如何写你的查询它可能已经足够投出的输出)为可空的T.

这里的解决scheme看起来比上面的要简单一些:

 var version = ctx.Entries .Where(e => e.Competition.CompetitionId == storeCompetition.CompetitionId) .Max(e =>(int?)e.Version); 

希望这可以帮助。

试试这个为你的最大值创build一个默认值。

 int version = ctx.Entries .Where(e => e.Competition.CompetitionId == storeCompetition.CompetitionId) .Max(e =>(int?)e.Version) ?? 0; 

你可以这样写一个简单的扩展方法,如果没有logging存在,它将返回typesT的默认值,然后将Max应用于该查询或存在logging的查询。

 public static T MaxOrEmpty<T>(this IQueryable<T> query) { return query.DefaultIfEmpty().Max(); } 

你可以像这样使用它

 maxId = context.Competition.Select(x=>x.CompetitionId).MaxOrEmpty(); 

我不能没有答案:)我已经testing了下面,它的工作原理,我没有检查生成的SQL,所以要小心,我会更新这一次,我已经testing了更多。

 var test = ctx.Entries .Where(e => e.Competition.CompetitionId == storeCompetition.CompetitionId) .MaxOrDefault(x => x.Version); public static TResult? MaxOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector) where TResult : struct { return source .Select(selector) .Cast<TResult?>() .Max(); } 

尝试这个:

 IEnumerable<AlertsResultset> alerts = null; alerts = (from POA in SDSEntities.Context.SDS_PRODUCT_ORDER_ALERT join A in SDSEntities.Context.SDS_ALERT on POA.ALERT_ID equals A.ALERT_ID orderby POA.DATE_ADDED descending select new AlertsResultset { ID = POA.PRODUCT_ORDER_ALERT_ID == null ? 0:POA.PRODUCT_ORDER_ALERT_ID , ITEM_ID = POA.ORDER_ID.HasValue ? POA.ORDER_ID.Value : POA.PRODUCT_ID.Value, Date = POA.DATE_ADDED.Value, orderType = SDSEntities.Context.SDS_ORDER.Where(o => o.ORDER_ID == POA.ORDER_ID.Value).FirstOrDefault().ORDER_TYPE, TransactionNumber = POA.PRODUCT_ID.HasValue ? (SDSEntities.Context.SDS_PRODUCT.Where(p => p.PRODUCT_ID == POA.PRODUCT_ID.Value).FirstOrDefault().TRANSACTION_NUMBER) : (SDSEntities.Context.SDS_ORDER.Where(o => o.ORDER_ID == POA.ORDER_ID.Value).FirstOrDefault().TRANSACTION_NUMBER), Publisher = POA.PRODUCT_ID.HasValue ? ( SDSEntities.Context.SDS_PRODUCT.Where(p => p.PRODUCT_ID == POA.PRODUCT_ID.Value).FirstOrDefault().PRODUCT_TYPE_NUMBER == "ISSUE" ? (from prod in SDSEntities.Context.SDS_PRODUCT join ji in SDSEntities.Context.SDS_JOURNAL_ISSUE on prod.PRODUCT_ID equals ji.PRODUCT_ID join j in SDSEntities.Context.SDS_JOURNAL on ji.JOURNAL_ID equals j.JOURNAL_ID where prod.PRODUCT_ID == POA.PRODUCT_ID select new { j.PUBLISHER_NAME }).FirstOrDefault().PUBLISHER_NAME : (from prod in SDSEntities.Context.SDS_PRODUCT join bi in SDSEntities.Context.SDS_BOOK_INSTANCE on prod.PRODUCT_ID equals bi.PRODUCT_ID join b in SDSEntities.Context.SDS_BOOK on bi.BOOK_ID equals b.BOOK_ID where prod.PRODUCT_ID == POA.PRODUCT_ID select new { b.PUBLISHER_NAME }).FirstOrDefault().PUBLISHER_NAME ) : (SDSEntities.Context.SDS_ORDER.Where(o => o.ORDER_ID == POA.ORDER_ID.Value).FirstOrDefault().PUBLISHER_NAME), Alert = A.ALERT_NAME, AlertType = A.ALERT_TYPE, IsFlagged = POA.IS_FLAGGED.Value, Status = POA.ALERT_STATUS }); 

关于什么

 query.Max<TSource,TResult?>(selector) 

我的意思是明确地设置结果types为空