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();
}
}