过滤实体框架上下文仅返回某些子元素

时间:2014-09-25 15:36:40

标签: c# asp.net-mvc entity-framework parent-child

美好的一天,ASP.NET,实体框架等的超级新手。非常精通直线编程,所以我首先要在新方法陷入其中之前尝试忘记旧方法。

我正在开发一个应用程序,它将跟踪FLEET项目(父项)及其所有FLEETEVENT项目(子项)。这两个是通过FleetId字段链接的。

我可以使用:Fleet fleet = db.Fleets.Find(id);并返回与id变量及其所有子元素匹配的父记录。

我要做的是仅返回子元素FLEETEVENT.STATUS == True

我尝试过使用LINQ表达式和DataLoadOptions.AssosiateWith,但是我得到了所有使用AssociateWith和转换错误的记录,试图使用LINQ表达式。

我认为这样做不应该太难,但我仍然坚持旧的思维方式。

代码snipets如下:

连接器型号:

public class FleetContext : DbContext
{
    public FleetContext() : base("DefaultConnection")
    {
    }

    public DbSet<Fleet> Fleets { get; set; }
    public DbSet<FleetEvent> FleetEvents { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new FleetConfiguration());
        modelBuilder.Configurations.Add(new FleetEventConfiguration());
    }
}

父模型:

public class Fleet : IObjectWithState
{
    public Fleet()
    {
        FleetEvents = new List<FleetEvent>();
        Status = true;
    }

    public System.Guid FleetId { get; set; }
    public string FleetType { get; set; }
    public string FleetNum { get; set; }
    public string FleetMake { get; set; }
    public string FleetModel { get; set; }
    public int FleetYear { get; set; }

    public bool Status { get; set; }
    public byte[] RowVersion { get; set; }

    public ObjectState ObjectState { get; set; }

    public virtual List<FleetEvent> FleetEvents { get; set; }
}

儿童模特:

public class FleetEvent : IObjectWithState
{
    public System.Guid FleetEventId { get; set; }
    public DateTime FleetEventDate { get; set; }
    public string FleetEventType { get; set; }
    public string FleetEventDesc { get; set; }

    public bool Status { get; set; }
    public byte[] RowVersion { get; set; }

    public System.Guid FleetId { get; set; }
    public Fleet Fleet { get; set; }

    public ObjectState ObjectState { get; set; }
}

使用LINQ,这是我正在使用的控制器中的代码:

var result = from f in db.Fleets
                     join fe in db.FleetEvents
                         on f.FleetId equals fe.FleetId
                     where ((f.FleetId == id) && (fe.Status == true))
                     select new { f, fe };

        Fleet fleet = result.ToList();

我已经通过LinqPad验证了LINQ语法是否正确,返回了我预期的结果。但是当我在代码中使用它时,我在Fleet fleet代码行中得到了转换错误。

非常感谢能指出正确方向的任何信息。

2 个答案:

答案 0 :(得分:3)

首先,在Entity框架中,您应该学习如何使用导航属性进行查询,并且不惜任何代价避免加入。

以下是样本

// return all FleetEvents where FleetEvent.Status = true for fleetID = n...
var result = db.FleetEvents
                 .Where(x=> x.Status == true && x.FleetID = id)
                 .Select( x=> new {
                        Fleet = x.Fleet,
                        FleetEvent = x
                     } );

// however result is of anonymous type, so you get Fleet and 
// FleetEvent both as properties of result

如果您想让任何有Status = true的孩子返回所有车队

var fleets = db.Fleets
               .Where( x=> x.FleetID == id && 
                           x.FleetEvents.Any(f=> f.Status == true));

// fleets is now and enumerable with all fleets with atleast 
// one child having Status=true

如果您想要返回所有拥有Status = true

的孩子的舰队
var fleets = db.Fleets
               .Where( x=> x.FleetID == id )
               .Select( x=> new {
                    Fleet = x,
                    FleetEvents = x.FleetEvents.Where(f=> f.Status == true)
               });

// here you have once again Anonymous type with Fleet and all FleetEvents 
// with Status = true

答案 1 :(得分:0)

你的问题是Fleet是一个类,而不是List&lt;&gt;()。所以你在调用ToList()时会失败。 同样选择f,fe不是舰队制造的。 :)要选择一个类,你会特别注意这个:

select new MyClass()
{
      MyField = f.Field,
      MyThingy = fe.thingy
}

您可能想做的事情是这样的:

Fleet fleet = new Fleet()
{
      FleetId = results.FleetId,
      FleetEventDate = results.FleetEventDate,
      ...
}

最难的部分是填充对象内的列表。但是你可以枚举fe实例并将每个实例添加到FleetEvents列表中。