我无法解决如何针对我的EF上下文编写linq查询以获得我想要的内容。
1)我拥有什么 没有分配外键的数据库,以及反向工程代码第一实体框架项目。我尝试手动添加虚拟类,因此EF可能会在DBcontext中创建隐含的外键,但我的.Include语句仍然出现错误。
没有包含我唯一能想到的就是使用左连接,但我还没有把它弄下来。最后我将有21个表来获取数据,但下表概述了我面临的大多数问题。
示例数据结构:
Table Human :HumanId,LastFoodEatenId,FavoriteFoodId,CurrentlyDesiredFoodId
餐食:FoodId,FoodName,FoodStuff
桌上玩具:HumanOwnerId,ToyId,ToyName
表宠物:HumanOwnerId,PetId,PetName,PetType
Table PetSurgery :PetId,SurgeryId,SurgeryPerformed
2)我想要什么 给定一个HumanID,我想从一个查询中获得一个compsite类或类似的东西。
Public Class QueryResult
{
public Human human {get;set;}
public Food LastEatenFood {get;set;}
public Food FavoriteFood {get;set;}
public Food CurrentlyDesiredFood {get;set;}
public IEnumerable<Toy> Toys {get;set;}
public IEnumerable<Pet> Pets {get;set;} //Includes surgeries if any
}
是否可以编写单个查询以在单个数据库命中中获取此类信息?我很好,有人只是确认这是不可能的。然后我至少可以请求我们添加与数据库的关系。
提前致谢,
答案 0 :(得分:1)
您可以使用linq查询多个不相关的表。
我会假设你的实体很多,但我们走了......
int humanId = 1234;
using (var context = new MyContext())
{
var human = (from h in context.Humans
join lf in context.Foods on h.LastFoodEatenId equals lf.foodId into lfg
from lf in lfg.DefaultIfEmpty() // left join
join ff in context.Foods on h.FavoriteFoodId equals lf.foodId into ffg
from ff in ffg.DefaultIfEmpty() // left join
join cf in context.Foods on h.CurrentlyDesiredFoodId equals lf.foodId into cfg
from cf in cfg.DefaultIfEmpty() // left join
join p in context.Pets on h.humanId equals p.humanId into pg // group
join t in context.Toys on h.humanId equals t.humanId into tg // group
where h.humanId = humanId
select new QueryResult { human = h, LastEatenFood = lf, FavoriteFood = ff, CurrentlyDesiredFood = cf, Toys = tg, Pets = pg }
).SingleOrDefault();
}
注意:我没有使用语法检查程序从内存中执行此操作,因此ymmv。也应该可以添加手术,但可能需要子查询。
答案 1 :(得分:1)
我尝试手动添加虚拟类
我认为你的意思是虚拟集合。如果它们不在数据库中,您可以在“代码优先”模型中定义关系。唯一的条件是外键必须引用EF知道作为主键的属性。所以你应该能够使用导航属性进行LINQ查询,而不是通过这样的模型进行这些详细的连接(简化为基本要素):
class Human
{
public int HumanId { get; set; }
public int LastFoodEatenId { get; set; }
public virtual Food LastEatenFood { get; set; }
public int FavoriteFoodId { get; set; }
public virtual Food FavoriteFood { get; set; }
public int CurrentlyDesiredFoodId { get; set; }
public virtual Food CurrentlyDesiredFood { get; set; }
public virtual ICollection<Toy> Toys { get; set; }
public virtual ICollection<Pet> Pets { get; set; }
}
class Food
{
public int FoodId { get; set; }
}
class Pet
{
public int PetId { get; set; }
public int HumanOwnerId { get; set; }
}
class Toy
{
public int ToyId { get; set; }
public int HumanOwnerId { get; set; }
}
和映射:
class HumanMapping : EntityTypeConfiguration<Human>
{
public HumanMapping()
{
HasOptional(h => h.LastEatenFood).WithMany()
.HasForeignKey(h => h.LastFoodEatenId);
HasOptional(h => h.FavoriteFood).WithMany()
.HasForeignKey(h => h.FavoriteFoodId);
HasOptional(h => h.CurrentlyDesiredFood).WithMany()
.HasForeignKey(h => h.CurrentlyDesiredFoodId);
HasMany(h => h.Toys).WithOptional().HasForeignKey(t => t.HumanOwnerId);
HasMany(h => h.Pets).WithOptional().HasForeignKey(t => t.HumanOwnerId);
}
}
EF将按名称约定推断主键。
现在您将能够执行LINQ语句,如:
context.Humans.Where(h => h.HumanId == id)
.Include(h => h.LastEatenFood)
.Include(h => h.FavoriteFood)
.Include(h => h.CurrentlyDesiredFood)
.Include(h => h.Toys)
.Include(h => h.Pets)
根据您的说明,我了解PetSurgery
应该是Pet
与另一个类Surgery
之间的联结类?)。无论如何,我认为你将管理创建正确的映射,看看这个例子。