繁体   English   中英

实体框架 - 有条件地包括相关实体

[英]Entity Framework - Conditionally include related entities

我维护一个API,它根据对人员列表的请求,根据请求返回不同的结果集。 例如,某些API客户端希望获取人员列表和他们的交互列表,其他人希望获得人员和他们的元数据列表。 所有这些都可以在请求返回人员的API方法时指定。

这似乎不起作用:

using (var dbcontext = new ExampleEntities())
{
    var query = dbcontext.People.AsQueryable();
    //determined in earlier application logic based on request
    if(includeMetadata)
    {
        query = query.Include("metadata");
    }
    //determined in earlier application logic based on request
    if(includeInteractions) 
    {
        query = query.Include("interactions");
    }
    /* ...SNIP... */
}

我不想做的是:

var query = dbcontext.People.Include("Metadata").Include("interactions");

即使请求的API客户端不需要它们,这意味着每个获取一个人的请求都将包括所有相关实体。

我也不想编写每种可能的逻辑组合:

if(includeMetadata && includeInteractions)
{
    var query = dbcontext.People.Include("Metadata").Include("interactions");

}
else if(includeMetadata)
{
    var query = dbcontext.People.Include("Metadata");
}
else if(includeInteractions)
{
    var query = dbcontext.People.Include("Interactions");
}
else
{
    var query = dbcontext.People;
}

这将导致难以维护的代码,但是,我意识到如果需要我可以生成代码。

你可以链接IQueryable

using (var dbcontext = new ExampleEntities())
{
    var query = dbcontext.People.AsQueryable();
    if(includeMetadata)
    {
        query = query.Include("metadata");
    }
    if(includeInteractions) 
    {
        query = query.Include("interactions");
    }    
}

如果用query替换u ,则第一个示例应该有效

 u = u.Include("metadata");

 query = query.Include("metadata");

在这里工作正常...使用EF 6 Log处理程序检查sql语句

[TestClass]
public void SomeTestClass
{
    [TestMethod]
    public void ShouldLoadOnlyRequiredCollections()
    {
        Database.SetInitializer(new DropCreateDatabaseAlways<HomesContext>());

        var db = new HomesContext();

        Assert.IsFalse(db.Homes.Any());

        var home = db.Homes.Create();

        db.Homes.Add(home);

        home.Staff.Add(new Staff { Name = "wilma" });
        home.Staff.Add(new Staff { Name = "betty" });

        home.Residents.Add(new Resident { Name = "fred" });
        home.Residents.Add(new Resident { Name = "barney" });

        db.SaveChanges();

        db = null;

        Database.SetInitializer(new DropCreateDatabaseIfModelChanges<HomesContext>());

        var sb = new StringBuilder();
        db = new HomesContext();

        db.Database.Log = ((s) => { sb.Append(s + "\r"); });

        Assert.IsTrue(db.Homes.Any());

        string log;

        log = sb.ToString();

        Assert.IsTrue(sb.ToString().Contains("FROM [dbo].[Homes]"));

        sb = new StringBuilder(); //ok get residents

        var q = db.Homes.Include("Residents");

        Assert.IsTrue(string.IsNullOrEmpty(sb.ToString()));

        var lst = q.ToList();

        log = sb.ToString();

        Assert.IsTrue(sb.ToString().Contains("[dbo].[Homes]"));
        Assert.IsTrue(sb.ToString().Contains("[dbo].[Residents]"));
        Assert.IsTrue(!sb.ToString().Contains("[dbo].[Staff]"));

        sb = new StringBuilder(); //get staff

        q = db.Homes.Include("Staff");

        Assert.IsTrue(string.IsNullOrEmpty(sb.ToString()));

        lst = q.ToList();

        log = sb.ToString();

        Assert.IsTrue(log.Contains("[dbo].[Homes]"));
        Assert.IsTrue(!log.Contains("[dbo].[Residents]"));
        Assert.IsTrue(log.Contains("[dbo].[Staffs"));



        sb = new StringBuilder(); //get residents and staff

        q = db.Homes.Include("Staff");

        q = q.Include("Residents");

        lst = q.ToList();

        log = sb.ToString();

        Assert.IsTrue(log.Contains("[dbo].[Homes]"));
        Assert.IsTrue(log.Contains("[dbo].[Residents]"));
        Assert.IsTrue(log.Contains("[dbo].[Staffs]"));




    }
}

public class HomesContext:DbContext
{
    public DbSet<Home> Homes { get; set; }
}

public class Home
{
    public Home()
    {
        Staff = new List<Staff>();
        Residents = new List<Resident>();
    }
    public int HomeId { get; set; }
    public string HomeName { get; set; }

    public int MaxResidents { get; set; }
    public int MaxStaff { get; set; }

    public int CurrentResidents { get; set; }

    [NotMapped]
    public int CurrentStaff { get; set; }

    public IList<Staff> Staff { get; set; }
    public IList<Resident> Residents { get; set; }
}

public class Staff
{
    public int StaffId { get; set; }
    public string Name { get; set; }
    public int HomeId { get; set; }
    public Home Home { get; set; }
}

public class Resident
{
    public int ResidentId { get; set; }
    public string Name { get; set; }

    public int HomeId { get; set; }
    public Home Home { get; set; }
}

暂无
暂无

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

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