[英]EF Many-to-Many removal not working as expected
我已经检查了至少20个不同的地方,以了解如何使用Entity Framework删除多对多注册表,并且我的代码似乎可以根据我发现的几乎所有解决方案工作。 不幸的是,无论如何,我都无法删除该关系。 这是代码:
using (var db = new Context())
{
var project = db.Projects.Single(p => p.Id == "myId");
foreach (var toRemove in project.Orders.Where(o =>
ordersToRemove.Select(otr => otr.Id).Contains(o.Id)).ToList())
{
project.Orders.Remove(toRemove);
}
db.SaveChanges();
}
我还试图强制在“ foreach”中进行删除,从“ db”中获取订单,并从中删除“项目”关系,只是为了进行测试,但这是没有用的。
作为信息,我已经对其进行了调试,并且在项目内部的Orders集合中,在“ SaveChanges”之前正确地删除了Orders。
在同一代码中,我有一个非常相似的流程来向Project添加订单,并且工作正常。
我在Context中手动进行了映射,如下所示:
modelBuilder.Entity<Project>()
.HasMany(p => p.Orders)
.WithMany(o => o.Projects)
.Map(pc =>
{
pc.MapLeftKey("ProjectId");
pc.MapRightKey("OrderId");
pc.ToTable("Projects_Orders");
});
我认为我无法弄清楚这很愚蠢,因此,我因此寻求您的帮助。 很抱歉,如果这是一个重复的问题,但是就像我之前说过的那样,我发现很多答案都表明该代码与我的代码完全相同。
更新:我发现了一个与我( 在此处 )有相同问题的人,并且我尝试使用标记的解决方案,但是没有用。 我还尝试清除所有集合,然后保存,然后再次添加应保留的订单,但这些订单也不起作用。 另一个解决方案是为相关表创建一个实体(类似于ProjectOrder),但我认为这太难看了。
最后,我使用了“ executesqlcommand”- 我对此并不感到骄傲 。 不幸的是,我只是不能浪费更多的时间。
更新 :先前的答案反映了如何删除“一对多”,这是我尝试过的更新示例,可以删除多对多关系而没有任何问题。 请忽略命名约定,因为我出于测试目的将它们放在一起非常快。
订单实体
namespace TestEF6.Data
{
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
[Table("ORDER")]
public partial class ORDER
{
public ORDER()
{
PROJECTS = new HashSet<PROJECT>();
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[StringLength(50)]
public string NAME { get; set; }
public virtual ICollection<PROJECT> PROJECTS { get; set; }
}
}
项目实体
namespace TestEF6.Data
{
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
[Table("PROJECT")]
public partial class PROJECT
{
public PROJECT()
{
ORDERS = new HashSet<ORDER>();
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[StringLength(50)]
public string NAME { get; set; }
public virtual ICollection<ORDER> ORDERS { get; set; }
}
}
上下文类
namespace TestEF6.Data
{
using System;
using System.Data.Entity;
public partial class ProjectManagerContext : DbContext
{
public ProjectManagerContext()
: base("name=ProjectManager")
{
}
public virtual DbSet<ORDER> ORDERs { get; set; }
public virtual DbSet<PROJECT> PROJECTs { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.Log = Console.WriteLine;
modelBuilder.Entity<PROJECT>()
.HasMany(p => p.ORDERS)
.WithMany(o => o.PROJECTS)
.Map(pc =>
{
pc.MapLeftKey("PROJECT_ID");
pc.MapRightKey("ORDER_ID");
pc.ToTable("PROJECT_ORDER");
});
}
}
}
单元测试
using System.Diagnostics;
using System.Linq;
using NUnit.Framework;
namespace TestEF6.Data.Tests
{
[TestFixture]
public class ProjectOrderTests
{
[Test]
public void Can_Remove_Projects_And_Orders_Relation()
{
using (var db = new ProjectManagerContext())
{
var proj1 = db.PROJECTs.Single(p => p.NAME == "TEST PROJ 1");
Debug.WriteLine($"Num of proj1 orders = [{proj1.ORDERS.Count}]");
foreach (var order in proj1.ORDERS.ToList())
{
Debug.WriteLine($"Removed proj order = [{proj1.NAME}] [{order.NAME}]");
proj1.ORDERS.Remove(order);
}
db.SaveChanges();
}
}
[Test]
public void Can_Add_Projects_And_Orders()
{
using (var db = new ProjectManagerContext())
{
var proj1 = new PROJECT { NAME = "TEST PROJ 1" };
var proj2 = new PROJECT { NAME = "TEST PROJ 2" };
var proj3 = new PROJECT { NAME = "TEST PROJ 3" };
db.PROJECTs.Add(proj1);
db.PROJECTs.Add(proj2);
db.PROJECTs.Add(proj3);
db.SaveChanges();
var order1 = new ORDER { NAME = "ORDER 1" };
var order2 = new ORDER { NAME = "ORDER 2" };
db.ORDERs.Add(order1);
db.ORDERs.Add(order2);
db.SaveChanges();
proj1.ORDERS.Add(order1);
proj1.ORDERS.Add(order2);
proj2.ORDERS.Add(order2);
db.SaveChanges();
}
}
}
}
这是配置文件
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
<connectionStrings>
<add name="ProjectManager" connectionString="data source=MYTESTSQL2014;initial catalog=ProjectManagerDb;user id=test_user;password=test$pwd!;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
这是在SQL Server中定义表结构并将联接表外键列设置为“允许为空”的方式。
检测结果
删除前PROJECT_ORDER表中有3行
删除后只有一行
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.