我有三个表:
材料:
喜欢:
访问者:
我想要一个像这样的对象
我尝试执行以下操作:
from mat in ctx.materials
let visitors = mat.VisitorsCollection.Where(x=>x.ReadNow).Count()
let likes = mat.LikesCollection.Where(x=>x.IsLiked).Count()
let iliked = mat.LikesCollection.Where(x=>x.UserID == myID && x.IsLiked).Any()
select new {
Material = mat,
Visitors = visitors,
Likes = likes,
Liked = iliked
}
我选择了一些材料,并且实体框架分别接收有关访问者数量的数据,依此类推。
我还尝试了以下方法:
from mat in ctx.materials
join lik in ctx.Likes.Where(x=>x.UserID == myID && x.IsLiked) on map.ID equals lik.MaterialID
select new {
Material = mat,
Liked = lik.Any()
}
但现在出现错误:
Microsoft.EntityFrameworkCore.Query:警告:LINQ表达式'Any()'无法翻译,将在本地进行评估。
答案 0 :(得分:3)
如果您使用的是实体框架,请考虑使用ICollections,而不要自己执行联接。
您有一个Materials
序列,其中每个Material
都具有零个或多个Likes
和零个或多个Visitors
,它们都是一对多关系,并且使用外国Material
的键。
如果您遵循entity framework code first conventions,将拥有与以下类似的课程
class Material
{
public int Id {get; set;}
public string Title {get; set;}
public string Content {get; set;}
// every Material has zero or more Likes (one-to-many)
public virtual ICollection<Like> Likes {get; set;}
// every Material has zero or more Visitors (one-to-many)
public virtual ICollection<Visitor> Visitors {get; set;}
}
喜欢和访问者:
class Like
{
public int Id {get; set;}
public bool IsLiked {get; set;}
...
// every Like belongs to exactly one Material, using foreign key
public int MaterialId {get; set;}
public virtual Material Material {get; set;}
}
class Visitor
{
public int Id {get; set;}
...
// every Visitor belongs to exactly one Material, using foreign key
public int MaterialId {get; set;}
public virtual Material Material {get; set;}
}
这是实体框架检测一对多关系所需的全部。可能是您想要不同的表名或列的不同标识符。在这种情况下,需要属性或流畅的API
在实体框架中,表的列由非虚拟属性表示。虚拟属性表示表之间的关系(一对多,多对多等)
一旦正确地定义了类,您的查询将非常简单直观:
要求:
从我的资料集中,给我每种资料,标题,内容,喜欢的数量以及访问者的数量:
var result = myDbContext.Materials
.Where(material => ...) // only if you don't want all Materials
.Select(material => new // from every Material make one new object
{ // containing the following properties
Title = material.Title,
Content = material.Content,
// if you want any information of the likes of this material, use property Likes
LikeCount = material.Likes
.Where(like => like.IsLiked) // optional, only if you don't want all likes
.Count(),
NrOfVisitors = material.Visitors
.Where(visitor => ...) // only if you don't want all visitors
.Count(),
});
换句话说:从我完整的材料集中,只保留那些... ...从其余所有材料中,制造一个新对象:
实体框架知道您的关系,并且知道需要GroupJoin。
答案 1 :(得分:0)
如果数据库中有外键,那么EF会在对象之间生成链接,因此您所需要做的就是:
var result = ctx.materials.Select(x =>
new SomeClass{
Material = x,
Visitors = x.Visitors.Where(v => v.ReadNow).Count(),
Likes = x.Likes.Where(y => y.IsLiked).Count(),
Liked = x.Likes.Where(z => z.IsLiked && z.UserID == myID).Count()
}).ToList();
语法可能并不完全正确,但是您明白了...