我在使用LINQ和Lambda编写的查询时遇到问题。 到目前为止,我的代码中出现了很多错误:
int id = 1;
var query = database.Posts.Join(database.Post_Metas,
post => database.Posts.Where(x => x.ID == id),
meta => database.Post_Metas.Where(x => x.Post_ID == id),
(post, meta) => new { Post = post, Meta = meta });
我是新手使用LINQ,所以我不确定这个查询是否正确。
#1楼
我发现,如果您熟悉SQL语法,那么使用LINQ查询语法会更清晰,更自然,并且更容易发现错误:
var id = 1;
var query =
from post in database.Posts
join meta in database.Post_Metas on post.ID equals meta.Post_ID
where post.ID == id
select new { Post = post, Meta = meta };
如果你真的坚持使用lambdas,你的语法有点偏。 这是使用LINQ扩展方法的相同查询:
var id = 1;
var query = database.Posts // your starting point - table in the "from" statement
.Join(database.Post_Metas, // the source table of the inner join
post => post.ID, // Select the primary key (the first part of the "on" clause in an sql "join" statement)
meta => meta.Post_ID, // Select the foreign key (the second part of the "on" clause)
(post, meta) => new { Post = post, Meta = meta }) // selection
.Where(postAndMeta => postAndMeta.Post.ID == id); // where statement
#2楼
您的密钥选择器不正确。 他们应该采用相关表格类型的对象,并返回要在连接中使用的密钥。 我想你的意思是:
var query = database.Posts.Join(database.Post_Metas,
post => post.ID,
meta => meta.Post_ID,
(post, meta) => new { Post = post, Meta = meta });
您可以在之后应用where子句,而不是作为键选择器的一部分。
#3楼
你可以用两种方式。 使用LINQPad (如果您是LINQ的新手,这是非常宝贵的)和虚拟数据库,我构建了以下查询:
Posts.Join(
Post_metas,
post => post.Post_id,
meta => meta.Post_id,
(post, meta) => new { Post = post, Meta = meta }
)
要么
from p in Posts
join pm in Post_metas on p.Post_id equals pm.Post_id
select new { Post = p, Meta = pm }
在这种特殊情况下,我认为LINQ语法更清晰(我在两者之间进行了更改,具体取决于最容易阅读的内容)。
我想指出的是,如果你的数据库中有适当的外键(post和post_meta之间),那么你可能不需要显式连接,除非你试图加载大量的记录。 您的示例似乎表明您正在尝试加载单个帖子及其元数据。 假设每个帖子都有很多post_meta记录,那么您可以执行以下操作:
var post = Posts.Single(p => p.ID == 1);
var metas = post.Post_metas.ToList();
如果你想避免n + 1问题,那么你可以明确地告诉LINQ to SQL一次性加载所有相关项目(尽管这可能是你更熟悉L2S时的一个高级主题)。 下面的示例说明“当您加载Post时,还会通过'Post_metas'属性表示的外键加载与其关联的所有记录”:
var dataLoadOptions = new DataLoadOptions();
dataLoadOptions.LoadWith<Post>(p => p.Post_metas);
var dataContext = new MyDataContext();
dataContext.LoadOptions = dataLoadOptions;
var post = Posts.Single(p => p.ID == 1); // Post_metas loaded automagically
对于相同类型或许多不同类型,可以在单个DataLoadOptions
集上进行许多LoadWith
调用。 如果你这么做,你可能只想考虑缓存。
#4楼
它可能是这样的
var myvar = from a in context.MyEntity
join b in context.MyEntity2 on a.key equals b.key
select new { prop1 = a.prop1, prop2= b.prop1};
#5楼
发布是因为当我开始LINQ + EntityFramework时,我盯着这些例子一天。
如果您正在使用EntityFramework,并且在Post
模型对象设置上有一个名为Meta
的导航属性,那么这很容易。 如果您正在使用实体并且没有该导航属性,您还在等什么?
database
.Posts
.Where(post => post.ID == id)
.Select(post => new { post, post.Meta });
如果你先做代码,你就这样设置了属性:
class Post {
[Key]
public int ID {get; set}
public int MetaID { get; set; }
public virtual Meta Meta {get; set;}
}
#6楼
Daniel对语法关系有一个很好的解释,但我把这个文档放在我的团队中,以便让他们更容易理解。 希望这有助于某人
#7楼
这个linq查询应该适合你。 它将获得所有发布元的帖子。
var query = database.Posts.Join(database.Post_Metas,
post => post.postId, // Primary Key
meta => meat.postId, // Foreign Key
(post, meta) => new { Post = post, Meta = meta });
等效的SQL查询
Select * FROM Posts P
INNER JOIN Post_Metas pm ON pm.postId=p.postId
#8楼
我做过这样的事情;
var certificationClass = _db.INDIVIDUALLICENSEs
.Join(_db.INDLICENSECLAsses,
IL => IL.LICENSE_CLASS,
ILC => ILC.NAME,
(IL, ILC) => new { INDIVIDUALLICENSE = IL, INDLICENSECLAsse = ILC })
.Where(o =>
o.INDIVIDUALLICENSE.GLOBALENTITYID == "ABC" &&
o.INDIVIDUALLICENSE.LICENSE_TYPE == "ABC")
.Select(t => new
{
value = t.PSP_INDLICENSECLAsse.ID,
name = t.PSP_INDIVIDUALLICENSE.LICENSE_CLASS,
})
.OrderBy(x => x.name);
#9楼
1等于1两个不同的表连接
var query = from post in database.Posts
join meta in database.Post_Metas on 1 equals 1
where post.ID == id
select new { Post = post, Meta = meta };