如何使用 Linq 通过交叉引用 table 连接实体 table
How to use Linq to join entity tables with a cross-reference table
首先让我说我对 Linq 比较陌生,但我似乎很快就掌握了其中的大部分内容。但是这个问题难倒了我。我找了又找都没用。
我正在使用代码优先并创建了 2 个模型,"Items" 和 "Keywords"。它们之间存在多对多关系。我的实体模型如下所示:
public class MyContext : DbContext
{
public MyContext() : base("name=DefaultDatabase") { }
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Mapping Xref table to the correct DB table
modelBuilder.Entity<Item>()
.HasMany(i => i.Keywords)
.WithMany(k => k.Items)
.Map(ik =>
{
ik.ToTable("ItemKeywords", "MySchema");
ik.MapLeftKey("ItemId");
ik.MapRightKey("KeywordId");
});
}
public virtual DbSet<Item> Items { get; set; }
public virtual DbSet<Keyword> Keywords { get; set; }
}
public class Item
{
public Item()
{
Keywords = new List<Keyword>();
}
public int ItemId { get; set; }
public string Text { get; set; }
public virtual List<Keyword> Keywords { get; set; }
}
public class Keyword
{
public Keyword()
{
Items = new HashSet<Item>();
}
public int KeywordId { get; set; }
public string Name { get; set; }
public virtual ICollection<Item> Items { get; set; }
}
据我所知,这非常简单。当我的迁移生成数据库时,我得到 3 tables、"Items"、"Keywords" 和 "ItemKeywords" 的交叉引用 table(我映射到"OnModelCreating" 方法)。
我遇到的问题是创建 Linq 查询(查询语法或方法语法,我不在乎)来重现:
SELECT DISTINCT
i.*
FROM
Items i
INNER JOIN ItemKeywords ik
ON i.ItemId = ik.ItemId
INNER JOIN Keywords k
ON ik.KeywordId = k.KeywordId
WHERE
k.KeywordId IN (1, 3, 5, 7, 9)
所以,基本上,我想要一个不同的项目列表,这些项目具有分配给它们的指定关键字之一。
我想我可以通过创建一个 ItemKeyword 模型来让它工作,但这似乎会破坏代码优先的意义。我会在那里添加一个额外的模型只是为了能够查询它。
有没有办法在不添加第三个外部参照模型的情况下使它工作?
谢谢!
我想你要找的是这样的查询:
var keywordIds = new List<int> {1, 3, 5, 7, 9};
var items = (from s in db.Items
from c in s.Keywords
where keywordIds.Contains(c.KeywordId)
select s).Distinct();
如果要将所有选定的项目都存入内存,请在查询结束时调用 ToList
方法。
首先让我说我对 Linq 比较陌生,但我似乎很快就掌握了其中的大部分内容。但是这个问题难倒了我。我找了又找都没用。
我正在使用代码优先并创建了 2 个模型,"Items" 和 "Keywords"。它们之间存在多对多关系。我的实体模型如下所示:
public class MyContext : DbContext
{
public MyContext() : base("name=DefaultDatabase") { }
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Mapping Xref table to the correct DB table
modelBuilder.Entity<Item>()
.HasMany(i => i.Keywords)
.WithMany(k => k.Items)
.Map(ik =>
{
ik.ToTable("ItemKeywords", "MySchema");
ik.MapLeftKey("ItemId");
ik.MapRightKey("KeywordId");
});
}
public virtual DbSet<Item> Items { get; set; }
public virtual DbSet<Keyword> Keywords { get; set; }
}
public class Item
{
public Item()
{
Keywords = new List<Keyword>();
}
public int ItemId { get; set; }
public string Text { get; set; }
public virtual List<Keyword> Keywords { get; set; }
}
public class Keyword
{
public Keyword()
{
Items = new HashSet<Item>();
}
public int KeywordId { get; set; }
public string Name { get; set; }
public virtual ICollection<Item> Items { get; set; }
}
据我所知,这非常简单。当我的迁移生成数据库时,我得到 3 tables、"Items"、"Keywords" 和 "ItemKeywords" 的交叉引用 table(我映射到"OnModelCreating" 方法)。
我遇到的问题是创建 Linq 查询(查询语法或方法语法,我不在乎)来重现:
SELECT DISTINCT
i.*
FROM
Items i
INNER JOIN ItemKeywords ik
ON i.ItemId = ik.ItemId
INNER JOIN Keywords k
ON ik.KeywordId = k.KeywordId
WHERE
k.KeywordId IN (1, 3, 5, 7, 9)
所以,基本上,我想要一个不同的项目列表,这些项目具有分配给它们的指定关键字之一。
我想我可以通过创建一个 ItemKeyword 模型来让它工作,但这似乎会破坏代码优先的意义。我会在那里添加一个额外的模型只是为了能够查询它。
有没有办法在不添加第三个外部参照模型的情况下使它工作?
谢谢!
我想你要找的是这样的查询:
var keywordIds = new List<int> {1, 3, 5, 7, 9};
var items = (from s in db.Items
from c in s.Keywords
where keywordIds.Contains(c.KeywordId)
select s).Distinct();
如果要将所有选定的项目都存入内存,请在查询结束时调用 ToList
方法。