2017-12-27 539 views
2

Linq实体无法使用DateTime.ToString(string)方法吗?使用下面的方法抛出异常LINQ to Entities does not recognize the method 'System.DateTime ToString(System.String)' method, and this method cannot be translated into a store expression.,这是预期的,因为它不能转换为SQL。Linq to Entities实现DateTime.ToString(字符串)

protected override bool TryGetEntitiesByKey(IEnumerable<string> keys, out IEnumerable<Trade> entities) 
{ 
    return this.TryLoadBase(x => keys.ToList().Contains(x.date.ToString("yyyyMMdd"), out entities); 
} 

在通用供应商,这是使用FUNC过滤从DB结果的代码,如下。

protected virtual bool TryLoadBase(Expression<Func<TEntity, bool>> filter, out IEnumerable<TEntity> entities) 
{ 
    bool loaded = true; 
    try 
    { 
    using (var db = this.dbContext) 
    { 
     entities = db.Set<TEntity>().Where(filter).ToList(); 
    } 
    } 
    catch (Exception ex) // Exception caught here 
    { 
    loaded = false; 
    entities = new List<TEntity>(); 
    } 
    return loaded; 
} 

后得到的例外前面提到的,我试过这个取代date.ToString(“年月日”):

SqlFunctions.StringConvert((double)notional.date.Year).Trim() + 
SqlFunctions.Replicate("0", 2 - SqlFunctions.StringConvert((double)notional.date.Month).Trim().Length) + SqlFunctions.StringConvert((double)notional.date.Month).Trim() + 
SqlFunctions.Replicate("0", 2 - SqlFunctions.StringConvert((double)notional.date.Day).Trim().Length) + SqlFunctions.StringConvert((double)notional.date.Day).Trim() 

虽然这个工作,它具有否则你得到的是直列关于LINQ to Entities不能识别该方法的相同消息。这意味着阅读起来很困难,不能被其他任何东西重复使用。

环顾四周后,我发现这个问题:(Reusable Calculations For LINQ Projections In Entity Framework),但我不愿意包括任何外部软件包只是为了解决这个问题。

还有Entity Framework 4/Linq: How to convert from DateTime to string in a query?的答案,但据我所知在接受的答案中使用AsEnumerable()将意味着枚举数据库集到内存中,由于内存限制,我无法做到这一点。而且我无法得到第二个答案能够正常工作,并且它会再次遭受上面SqlFunctions混乱的问题。

如果这是不可能的,是否有人能够提供一个清洁的替代SqlFunctions块?

+3

将键转换为日期而不是日期转换为字符串可能会更好,因为您要过滤的列是日期类型。 – Evk

+0

请注意,捕获_any_异常并仅仅返回一个空列表可能不是一个好设计 - 您不能分辨是否存在潜在错误(或更糟糕的是,该错误是什么),或者如果您的筛选器没有返回任何对象。 –

+0

将日期转换为字符串以供机器使用时,指定'CultureInfo'就像'CultureInfo.Invariant'是明智的。否则,你可能会得到一个令人惊讶的结果。举一个具体的例子,如果你的代码执行的用户的文化是泰国的,那么2017年的(UTC)年将被格式化为2560. –

回答

1

您正在要求提供者将呼叫DateTime.ToString(format)转换为不受支持的SQL。您可能还需要使用EntityFunctions.TruncateTime比较只有日期部分(因为这就是字符串比较会做):

你要么需要解析的关键日期/时间对象或传递一个IEnumerable<DateTime>代替:

protected override bool TryGetEntitiesByKey(IEnumerable<string> keys, out IEnumerable<Trade> entities) 
{ 
    var keyDates = keys.Select(s => DateTime.ParseExact("yyyyMMdd")).ToList(); 
    return this.TryLoadBase(x => keyDates.Contains(EntityFunctions.TruncateTime(x.date)), out entities); 
}