C# 使用日期选择器和实体框架6获取两个日期之间的所有日期

C# 使用日期选择器和实体框架6获取两个日期之间的所有日期,c#,winforms,entity-framework,linq,entity-framework-6,C#,Winforms,Entity Framework,Linq,Entity Framework 6,我的表格上有两个日期选择器。我想要一个函数,它将返回特定表中的所有日期时间,这些表是这两个日期之间特定列的值 我的方法如下所示: public DateTime[] GetAllArchiveDates(string username = null) { var result = new DateTime[0]; if (username != null) { result = this._context.archive.OrderBy(s =>

我的表格上有两个日期选择器。我想要一个函数,它将返回特定表中的所有日期时间,这些表是这两个日期之间特定列的值

我的方法如下所示:

public DateTime[] GetAllArchiveDates(string username = null)
{
    var result = new DateTime[0];

    if (username != null)
    {
        result = this._context.archive.OrderBy(s => s.IssuingDate).Where(s => s.insertedBy == username).Select(s => s.issuing_date).Distinct().ToArray();
    }
    else
    {
        result = this._context.archive.OrderBy(s => s.IssuingDate).Select(s => s.issuing_date).Distinct().ToArray();
    }

    return result;
}
但我得到了这个错误:

System.NotSupportedException:'指定的类型成员'IssuingDate'在LINQ to实体中不受支持。仅支持初始值设定项、实体成员和实体导航属性。”

如何执行此操作?

错误消息的原因 您应该了解IEnumerable和IQueryable之间的区别

实现IEnumerable的类的对象包含它所表示的项序列上要枚举的所有内容。你可以要求序列的第一项,一旦你有了一项,你可以要求下一项,直到没有更多的项目

另一方面,实现IQueryable的类的对象保存了请求另一个进程提供数据以创建IEnumerable序列的所有内容。为此,它包含一个表达式和一个提供程序

表达式是在开始枚举IQueryable后必须创建何种IEnumerable的通用表示形式

提供者知道谁必须执行查询,并且知道如何将表达式转换为执行者理解的格式,例如SQL

有两种LINQ语句。那些使用延迟执行的,那些不使用。可以识别延迟函数,因为它们返回IQueryable或IEnumerable。例如Where、Select、GroupBy等

非延迟函数返回一个TResult:ToList、ToDictionary、FirstOrDefault、Max

只要连接延迟LINQ函数,就不会执行查询,只会更改表达式。一旦开始枚举(显式使用GetEnumerator和MoveNext,或隐式使用foreach、ToList、Max等),表达式将发送给提供者,提供者将其转换为SQL并执行查询。结果表示为IEnumerable,对其执行GetEnumerator

这跟我的问题有什么关系

因为表达式必须翻译成SQL,所以它不能保存您发明的任何内容。毕竟,SQL不知道您的函数。事实上,有很多标准函数不能在IQueryable中使用。看

遗憾的是,您忘了给我们归档类定义,但我认为它不是POCO:它包含的函数和属性不仅仅是get/set。我认为发布日期不仅仅是获取/设置

对于IQueryables,您应该使类保持简单:在查询期间仅使用{get;set;},仅此而已。在将IQueryable具体化为IEnumerable后,可以调用其他函数,IEnumerable将在本地进程中执行

回到你的问题上来 因此,您有一个具有表存档的数据库,其中至少有列IssuingDate和InsertedBy。看来InsertedBy只是一个字符串。它可以是用户表的外键。这对答案影响不大

遵循下面的步骤,这将导致以下类

class Archive
{
    public int Id {get; set;}
    public DateTime IssuingDate {get; set;}
    public string InsertedBy {get; set;}
    ...
}

public class MyDbContext : DbContext
{
     public DbSet<Archive> Archives {get; set;}
}
如果我看一下您的代码,您不会在日期之间选择归档。您可以使用用户名、排序、选择distinct。。。有点奇怪的是,您首先订购了所有一百万份档案,然后决定只保留属于userName的十份档案,如果您有几个相同的发行日期,则决定删除重复的档案。在开始订购之前,先限制发行日期不是更有效吗

public static IQueryable<archive> ToIssuingDatesOfUser(this IQueryable<archive> archives,
    string userName)
{
    // first limit the number of archives, depdning on userName,
    // then select the IssuingDate, remove duplicates, and finally Order
    var archivesOfUser = (userName == null) ? archives :
        archives.Where(archive => archive.InsertedBy == userName);

   return archivesOfUser.Select(archive => archive.IssuingDate)
                        .Distinct()
                        .OrderBy(issuingDate => issuingDate);
}

在OrderBy中有s.IssuingDate,但在Select中有s.IssuingDate。s.IssuingDate和s.IssuingDate之间有什么区别?哦,就是这样。s、 IssuingDate是通过分部类添加的字符串类型的属性,它是该日期的文本表示形式。。。我的错。。。非常感谢。不客气。嘿,谢谢你详细而有用的回答。我想我会按照你的建议去做!
public static IQueryable<archive> ToIssuingDatesOfUser(this IQueryable<archive> archives,
    string userName)
{
    // first limit the number of archives, depdning on userName,
    // then select the IssuingDate, remove duplicates, and finally Order
    var archivesOfUser = (userName == null) ? archives :
        archives.Where(archive => archive.InsertedBy == userName);

   return archivesOfUser.Select(archive => archive.IssuingDate)
                        .Distinct()
                        .OrderBy(issuingDate => issuingDate);
}
public ICollection<string> GetIssuingDatesOfUserBetweenDates(string userName, 
    DateTime startDate,
    DateTime endDate)
{
    using (var dbContext = new MyDbContext(...))
    {
        return dbContext.Archives
               .BetweenDates(startDate, endDate)
               .ToIssuingDatesOfUser(userName)
               .ToList();
    }
}