繁体   English   中英

EF Lambda 包含导航属性

[英]EF Lambda include navigation properties

我有以下对象,名为 Filter ,具有以下属性:

    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Type> Types{ get; set; }
    public virtual ICollection<Step> Steps { get; set; }
    public virtual ICollection<Flow> Flows { get; set; }
    public virtual ICollection<Room> Rooms { get; set; }

当我从数据库中选择过滤器列表时,我不知道如何包含集合(类型、步骤、流程、房间)。 我的代码如下:

var filters = (
            from filter in dbContext.DbSet<Filter>()
            let rooms = (
                from r in dbContext.DbSet<Room>()
                select r
                )
            let eventTypes = (
                from t in dbContext.DbSet<Type>()
                select t
                )
            let processFlows = (
                from f in dbContext.DbSet<Flow>()
                select f
                )
            let processFlowSteps = (
                from s in dbContext.DbSet<Step>()
                select s
                )
            select filter
            ).ToList();

我的Filter集合返回了,但是里面的集合是空的。 你能告诉我我怎样才能做到这一点?

Ps:由于性能问题,我不想使用 Include,我不喜欢 Entity Framework 生成查询的方式,我想这样做。

您需要使用Include扩展方法:

var filters=dbContext.DbSet<Filter>()
                     .Include(f=>f.Types)
                     .Include(f=>f.Steps)
                     .Include(f=>f.Flows)
                     .Include(f=>f.Rooms)
                     .ToList()

更新

@MrSilent, Include扩展方法正是为了加载相关实体而制作的,我认为您拥有的另一个选项是执行原始 sql ,但是您正在做的方式并不是您对数据库进行四次往返的方法,并且您需要改用 join 来获取相关实体, Include为您生成这些连接,而这只是一次往返。

这是,例如,我猜你可以这样做的另一种方式,但同样,它违背了使用 EF 的目的,你的模型的想法也是表示表之间的关系,而不仅仅是单独表示它们

var query= from f in context.DbSet<Filter>()
           from s in f.Steps
           from r in f.Rooms
           from t in f.Types
           from fl in f.Flows
           select new {f, s, r, t, fl};

你的方法有效,你只是做错了。

要包含导航属性,您所要做的就是一个子选择(使用 linq),例如:

var filters = (from filter in dbContext.DbSet<Filter>()
                select new Filter
                {
                    filter.Id,
                    filter.Name,
                    Rooms = (from r in dbContext.DbSet<Room>()
                            where r.FilterId == filter.Id
                            select r).ToList()
                }).ToList();

请记住,在您调用返回方法(ToList、Any、FirstOrDefault 等)之前,EF 不会执行查询。 有了这个,而不是通过不使用 Include() 来执行那些你想避免的丑陋查询,它只会触发两个查询并正确分配你想要的对象中的值。

您可以使用延迟加载,方法如下:

您首先需要获得 Include 倾向于虚拟的属性,然后是受保护访问类型的空构造函数才能很好地完成您的工作。

public virtual ICollection<Type> Types{ get; set; }
public virtual ICollection<Step> Steps { get; set; }
public virtual ICollection<Flow> Flows { get; set; }
public virtual ICollection<Room> Rooms { get; set; }

 //FOR EF !
 protected Filter() { }

我认为此解决方案将解决您的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM