简体   繁体   English

EF多对多删除无法正常工作

[英]EF Many-to-Many removal not working as expected

I've checked in at least 20 different places about how to delete a many-to-many registry using Entity Framework, and my code seems to be working according to almost all solutions I found. 我已经检查了至少20个不同的地方,以了解如何使用Entity Framework删除多对多注册表,并且我的代码似乎可以根据我发现的几乎所有解决方案工作。 Unfortunately, I can't delete the relationship, no matter what. 不幸的是,无论如何,我都无法删除该关系。 Here's the code: 这是代码:

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();
}

I also tried to force the removal inside the "foreach", getting the order from "db" and removing the Project relationship from it, just to test, but it was useless. 我还试图强制在“ foreach”中进行删除,从“ db”中获取订单,并从中删除“项目”关系,只是为了进行测试,但这是没有用的。

As a matter of information, I've debugged it and my Orders collection inside project had the Orders removed correctly right before "SaveChanges". 作为信息,我已经对其进行了调试,并且在项目内部的Orders集合中,在“ SaveChanges”之前正确地删除了Orders。

In the same code I have a very similar flow to add orders to Project and it works fine. 在同一代码中,我有一个非常相似的流程来向Project添加订单,并且工作正常。

I did the mapping in Context manually, like this: 我在Context中手动进行了映射,如下所示:

modelBuilder.Entity<Project>()
            .HasMany(p => p.Orders)
            .WithMany(o => o.Projects)
            .Map(pc =>
            {
                pc.MapLeftKey("ProjectId");
                pc.MapRightKey("OrderId");
                pc.ToTable("Projects_Orders");
            });

I believe it's something silly that I can't figure out, so because of it I ask your help. 我认为我无法弄清楚这很愚蠢,因此,我因此寻求您的帮助。 Sorry if it's a duplicated question, but like I said before, I found a lot of answers that the code is pretty the same as mine. 很抱歉,如果这是一个重复的问题,但是就像我之前说过的那样,我发现很多答案都表明该代码与我的代码完全相同。

UPDATED: I found out someone which had the same issue as me ( here ), and I tried to use the marked solution, but didn't work. 更新:我发现了一个与我( 在此处 )有相同问题的人,并且我尝试使用标记的解决方案,但是没有用。 I also tried to clear all collection, then save, and then add again the orders that should remain, and didn't work either. 我还尝试清除所有集合,然后保存,然后再次添加应保留的订单,但这些订单也不起作用。 Another solution was to create an entity for the related table (something like ProjectOrder), but I thought it would be too damn ugly. 另一个解决方案是为相关表创建一个实体(类似于ProjectOrder),但我认为这太难看了。

In the end, I used "executesqlcommand" - and I'm not proud of it . 最后,我使用了“ executesqlcommand”- 我对此并不感到骄傲 I just couldn't waste more time in it, unfortunately. 不幸的是,我只是不能浪费更多的时间。

UPDATED : Previous answer was reflecting how to delete One-Many, here is an updated sample that I tried and I am able to delete Many-To-Many relationship without any issues. 更新 :先前的答案反映了如何删除“一对多”,这是我尝试过的更新示例,可以删除多对多关系而没有任何问题。 Please ignore the naming convention as I put this together real quick for testing purpose. 请忽略命名约定,因为我出于测试目的将它们放在一起非常快。

ORDER Entity 订单实体

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; }
    }
}

PROJECT entity 项目实体

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; }
    }
}

Context class 上下文类

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");
            });
        }
    }
}

UNIT TESTS 单元测试

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();
            }
        }


    }
}

Here is config file 这是配置文件

<?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>

Here is how the table structure in SQL server is defined and the join table foreign key columns are set to Allow nulls. 这是在SQL Server中定义表结构并将联接表外键列设置为“允许为空”的方式。

项目订单关系图

Test Results 检测结果

在此处输入图片说明

There were 3 rows in PROJECT_ORDER table before deletion 删除前PROJECT_ORDER表中有3行

在此处输入图片说明

There is just one row after the delete 删除后只有一行

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM