【问题标题】:Add a filter on a DbSet that is included on a related DbSet? [duplicate]在相关 DbSet 中包含的 DbSet 上添加过滤器? [复制]
【发布时间】:2017-12-06 05:27:08
【问题描述】:

以下是幕后的一些东西。

public class User : BaseTransactionModel
{
    public Guid UserId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class Transaction
{

    public int TransactionId { get; set; }
    public string TransactionName { get; set; }
    public int TransactionHistoryId { get; set; }

    public virtual TransactionHistory TransactionHistory { get; set; }
}

public class TransactionHistory
{
    public int TransactionHistoryId { get; set; }
    public DateTime CreatedDateTime { get; set; }
    public Guid UserId { get; set; }
    public int TransactionId { get; set; }

    public virtual ICollection<User> Users { get; set; }
    public virtual ICollection<Transaction> Transactions { get; set; }
}

public class BaseTransactionModel
{

    public int TransactionHistoryId { get; set; }
    public int TransactionId { get; set; }

    public virtual TransactionHistory TransactionHistory { get; set; }
    public virtual Transaction Transaction { get; set; }
}

对于上述实体,我试图在指定日期从 User 获取所有 Transactions

所以我尝试在 Transaction DbSet 中同时包含 UserTransactionHistory

Context.Transaction
    .Include(t => t.User)
    .Include(t => t.TransactionHistory)
    ...

我想添加一个 where 子句,从交易历史实体中的日期过滤交易:

Context.Transaction
    .Include(t => t.User)
    .Include(t => t.TransactionHistory)
    .Where(t => t.TransactionHistory.CreatedDateTime <= StartDateFilter && t.TransactionHistory.CreatedDateTime >= EndDateFilter)

但不能这样做。因为 TransactionHistory 也是一个实体列表(或其他任何名称)。

获得我想要实现的目标的可能解决方案是什么?

PS:我是 EF 的新手,标题可能会产生误导。如果是这样,请随时更新。

【问题讨论】:

  • 你的模型类看起来不像他们应该的那样。尝试研究,应如何在类中定义关系(使用导航属性)。
  • @Nikolaus 我对上面的示例课程表示不满。感谢您的建议,我一定会看看它。

标签: c# entity-framework entity-framework-6 ef-code-first


【解决方案1】:

您可能需要重新考虑您的课程设计,例如

public class User
    {
        public Guid UserId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public virtual ICollection<Transaction> TransactionHistory { get; set; }
    }

    public class Transaction
    {    
        public int TransactionId { get; set; }
        public string TransactionName { get; set; }
        public DateTime CreatedDateTime { get; set; }
    }

然后要获得您需要的交易,您的查询可能是这样的:

 var result = Context.User
                .Where(u => u.UserId == myguid)
                .Select(t => new
                {
                    UserId = t.UserId,
                    Transactions = t.TransactionHistory.Where(x => x.CreatedDateTime >= StartDateFilter && x.CreatedDateTime <= EndDateFilter)
                })
                .ToList();

【讨论】:

  • “你可能需要重新考虑你的班级设计”...我知道这可能是解决方案之一,但我不想这样做,因为这是我正在尝试的其他人的项目探索,我避免修改它的任何类模型。如果除此之外没有其他可能的解决方案,那么这可能是我最后的手段。
【解决方案2】:

您正在寻找的是能够过滤包含的实体。

有两种过滤包含实体的方法:

  • 使用投影(参见@majita 答案)
  • 使用第三方库

免责声明:我是项目的所有者Entity Framework Plus

EF+ Query IncludeFilter 允许轻松过滤包含的实体。

Context.Transaction
    .IncludeFilter(t => t.User)
    .IncludeFilter(t => t.TransactionHistory
        .Where(x => x.TransactionHistory.CreatedDateTime <= StartDateFilter && x.TransactionHistory.CreatedDateTime >= EndDateFilter))

在引擎盖下,库完全是一个投影。

一个限制是所有Include,但现在使用IncludeFilter 调用,即使没有指定过滤器,例如User

维基:EF+ Query Include Filter

【讨论】:

    【解决方案3】:

    试试这个

    Context.Transaction
        .Where(t => t.TransactionHistory.CreatedDateTime <= StartDateFilter && t.TransactionHistory.CreatedDateTime >= EndDateFilter)
    .Select(x=> new {x.User,x.TransactionHistory});
    

    或者这个

    Context.Transaction
    .Where(t => t.TransactionHistory.CreatedDateTime <= StartDateFilter && t.TransactionHistory.CreatedDateTime >= EndDateFilter)
    .Include(t => t.User)
    .Include(t => t.TransactionHistory)
    

    【讨论】:

    • 由于导航属性错误,这不起作用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-07
    • 1970-01-01
    • 2021-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多