如何在LINQ中使用CreateDateTime实体表达式

时间:2016-11-02 15:47:23

标签: c# .net entity-framework linq

因为如果您尝试在LINQ表达式中使用DateTime,您将获得:

Only parameterless constructors and initializers are supported in LINQ to Entities.

最好的方法是使用DbFunctions.CreateDateTime Methodhttps://msdn.microsoft.com/en-us/library/dn218443(v=vs.113).aspx

不工作示例:

await ctx.Example.AsNoTracking()
    .Where(e => e.Id == id)
    .Select(e => new EducationDTO {
            StartDate =  new DateTime(e.StartDate, 1, 1)
            EndDate = new DateTime(e.EndDate, 1, 1)
    })
    .ToListAsync().ConfigureAwait(false);

尝试示例:

await ctx.Example.AsNoTracking()
    .Where(e => e.Id == id)
    .Select(e => new EducationDTO {
            StartDate =  DbFunctions.CreateDateTime(e.StartDate, 1, 1, null, null, null) ?? DateTime.Now,
            EndDate = DbFunctions.CreateDateTime(e.EndDate, 1, 1, null, null, null) ?? DateTime.Now,
    })
    .ToListAsync().ConfigureAwait(false);

在我尝试使用CreateDateTime示例时,CreateDatetime将为null,我将获得DateTime.Now

我做错了什么?

2 个答案:

答案 0 :(得分:4)

假设非工作示例是正确的(即e.StartDate / e.EndDateint并且代表年份),唯一的问题是不受支持的DateTime构造函数。

正如您所提到的,正确的方法是DbFunctions.CreateDateTime,它具有以下签名:

public static Nullable<DateTime> CreateDateTime(
    Nullable<int> year,
    Nullable<int> month,
    Nullable<int> day,
    Nullable<int> hour,
    Nullable<int> minute,
    Nullable<double> second
)

文档中未提及的内容(尽管这是典型的数据库表达式行为),当任何参数为null时,结果为null。这也意味着如果所有参数 null ... - 实际上,结果也不是null

因此,您方案中的正确用法如下:

.Select(e => new EducationDTO {
        StartDate = DbFunctions.CreateDateTime(e.StartDate, 1, 1, 0, 0, 0).Value,
        EndDate = DbFunctions.CreateDateTime(e.EndDate, 1, 1, 0, 0, 0).Value,
})

答案 1 :(得分:1)

这些方面的东西会对你有用吗?

免责声明 - 我仍然不能100%确定您的输入/输出情况。您有DateTimeDateTime?,您期望从哪里转换,等等

创建扩展程序

public static class Ext
{

    public static DateTime? SpecialDate(this DateTime? v)
    {
        if (!v.HasValue) return null;
        return new DateTime(v.Value.Year, 1, 1);
    }

    public static DateTime? SpecialDate2(this DateTime? v)
    {
        if (!v.HasValue) return null;
        // neither this
        return new DateTime().AddYears(v.Value.Year - 1);
        // or this - uses parameterized constructor
        //return DateTime.MinValue.AddYears(v.Value.Year - 1);
    }
}

用法

    DateTime? dt2 =  null;
    DateTime? dt1 =  DateTime.Now;

    Console.WriteLine(dt2.SpecialDate());
    Console.WriteLine(dt1.SpecialDate());
    Console.WriteLine(dt1.SpecialDate2());

结果

<-- this is empty string <br>
     

1/1/2016 12:00:00 AM   1/1/2016 12:00:00 AM

在你的情况下,它将是

StartDate = e.StartDate.SpecialDate()