我维护一个API,该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;
}
这将导致难以维护的代码,但是,我知道如果需要我可以生成代码。
答案 0 :(得分:10)
你可以链接IQueryable的
using (var dbcontext = new ExampleEntities())
{
var query = dbcontext.People.AsQueryable();
if(includeMetadata)
{
query = query.Include("metadata");
}
if(includeInteractions)
{
query = query.Include("interactions");
}
}
答案 1 :(得分:0)
如果您将u
替换为query
u = u.Include("metadata");
与
query = query.Include("metadata");
答案 2 :(得分:0)
在这里运行正常...使用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; }
}