更新在 EF 中添加相关行的行(多对多)
Update a row adding a relationed row in EF (many-to-many)
我有两个实体:Order
和 Item
以及它们之间的多对多关系。我有一个接收 ItemId 作为参数的方法,如下所示:
public void AddItems(int OrderId, int ItemId)
{
Item item = db.ItemSet.SingleOrDefault(i => i.Id == ItemId);
Order order = db.OrderSet.SingleOrDefault(o => o.Id == OrderId);
order.Items.Add(item);
db.SaveChanges();
}
ItemSettable中有很多行,所以第一个查询很重。有没有一种方法可以在不先在 "ItemSet" table 上进行查询的情况下将商品添加到订单中?我的意思是,我可以将 ItemId 直接添加到 Order.Items 或类似的东西吗?
Item item = new Item { ID = ItemId };
Order order = new Order { ID = OrderId };
db.ItemSet.Attach(item);
db.OrderSet.Attach(order);
order.Items.Add(item);
db.SaveChanges();
请确保您的订单中包含此内容 class:
public Order()
{
Items = new List<Item>();
}
所以你不会在order.Items.Add(item);
中得到空指针异常
因此您可以对实体进行建模,因此:
public DbSet<Item> ItemSet {get;set;}
public DbSet<Order> OrderSet {get;set;}
public DbSet<ItemOrder> ItemOrders {get;set;}
public class Item
{
public int Id {get;set;}
}
public class Order
{
public int Id {get;set;}
}
public class ItemOrder
{
[Key, Column(Order = 0)]
public int ItemId {get;set;}
[Key, Column(Order = 1)]
public int OrderId {get;set;}
}
所以为了更新:
public void AddItems(int OrderId, int ItemId)
{
var itemExists = db.ItemOrders.FirstOrDefault(x => x.OrderId == OrderId && x.ItemId == ItemId);
if (itemExists != null) return;
db.ItemOrders.Add(new ItemOrder { OrderId = OrderId, ItemId = ItemId });
db.SaveChanges();
}
然后您可以使用 LINQ .Join()
进行查询,非常简单。
为了完整起见,OP 提到导航属性现在已经消失。所以如果你知道 OrderId
那么你可以简单地做:
var items = db.ItemOrders.GroupJoin(
db.ItemSet,
io => io.ItemId,
i => i.Id,
(itemOrder, items) => items)
.ToList();
因此,为了引导您完成,GroupJoin
要求提供您要加入的数据的 IQueryable
/IEnumerable
。
第二个参数是初始数据集的字段,即ItemOrders
您要加入的数据集。
第三个参数是要加入的集合的字段,即ItemSet
。
第四个参数基本上是一个 Select
,您会看到一个 Func
签名,大致 (ItemOrder itemInFirstSet, IEnumerable<Item> itemsThatAreJoined)
。
您可以将相同的逻辑应用于 LINQ Join
扩展。但不是 itemsThatAreJoined
,而是 itemThatIsJoined
。所以区别是 GroupJoin
会找到多个匹配的实体,Join
只会找到一个。
这不是详细的解释,更多的是概述
我有两个实体:Order
和 Item
以及它们之间的多对多关系。我有一个接收 ItemId 作为参数的方法,如下所示:
public void AddItems(int OrderId, int ItemId)
{
Item item = db.ItemSet.SingleOrDefault(i => i.Id == ItemId);
Order order = db.OrderSet.SingleOrDefault(o => o.Id == OrderId);
order.Items.Add(item);
db.SaveChanges();
}
ItemSettable中有很多行,所以第一个查询很重。有没有一种方法可以在不先在 "ItemSet" table 上进行查询的情况下将商品添加到订单中?我的意思是,我可以将 ItemId 直接添加到 Order.Items 或类似的东西吗?
Item item = new Item { ID = ItemId };
Order order = new Order { ID = OrderId };
db.ItemSet.Attach(item);
db.OrderSet.Attach(order);
order.Items.Add(item);
db.SaveChanges();
请确保您的订单中包含此内容 class:
public Order()
{
Items = new List<Item>();
}
所以你不会在order.Items.Add(item);
因此您可以对实体进行建模,因此:
public DbSet<Item> ItemSet {get;set;}
public DbSet<Order> OrderSet {get;set;}
public DbSet<ItemOrder> ItemOrders {get;set;}
public class Item
{
public int Id {get;set;}
}
public class Order
{
public int Id {get;set;}
}
public class ItemOrder
{
[Key, Column(Order = 0)]
public int ItemId {get;set;}
[Key, Column(Order = 1)]
public int OrderId {get;set;}
}
所以为了更新:
public void AddItems(int OrderId, int ItemId)
{
var itemExists = db.ItemOrders.FirstOrDefault(x => x.OrderId == OrderId && x.ItemId == ItemId);
if (itemExists != null) return;
db.ItemOrders.Add(new ItemOrder { OrderId = OrderId, ItemId = ItemId });
db.SaveChanges();
}
然后您可以使用 LINQ .Join()
进行查询,非常简单。
为了完整起见,OP 提到导航属性现在已经消失。所以如果你知道 OrderId
那么你可以简单地做:
var items = db.ItemOrders.GroupJoin(
db.ItemSet,
io => io.ItemId,
i => i.Id,
(itemOrder, items) => items)
.ToList();
因此,为了引导您完成,GroupJoin
要求提供您要加入的数据的 IQueryable
/IEnumerable
。
第二个参数是初始数据集的字段,即ItemOrders
您要加入的数据集。
第三个参数是要加入的集合的字段,即ItemSet
。
第四个参数基本上是一个 Select
,您会看到一个 Func
签名,大致 (ItemOrder itemInFirstSet, IEnumerable<Item> itemsThatAreJoined)
。
您可以将相同的逻辑应用于 LINQ Join
扩展。但不是 itemsThatAreJoined
,而是 itemThatIsJoined
。所以区别是 GroupJoin
会找到多个匹配的实体,Join
只会找到一个。
这不是详细的解释,更多的是概述