EF多对多删除无法按预期工作

时间:2017-02-10 20:42:27

标签: c# entity-framework linq many-to-many

我已经在至少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集合已经在#34; SaveChanges"之前正确删除了订单。

在相同的代码中,我有一个非常类似的流程来向Project添加订单,它工作正常。

我在上下文中手动完成了映射,如下所示:

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

我相信这是一件令人愚蠢的事情,我无法弄明白,因此我会请求你的帮助。对不起,如果它是一个重复的问题,但就像我之前说过的那样,我发现了许多答案,代码与我的代码非常相似。

更新:我找到了一个与我有同样问题的人(here),我尝试使用标记的解决方案,但没有成功。我还试图清除所有收藏,然后保存,然后再次添加应保留的订单,并且也没有工作。另一个解决方案是为相关表创建一个实体(类似于ProjectOrder),但我认为它太丑了。

最后,我使用&#34; executionqlcommand&#34; - 我并不为此感到骄傲。不幸的是,我无法在其中浪费更多时间。

1 个答案:

答案 0 :(得分:0)

更新:以前的答案反映了如何删除One-Many,这是我尝试过的更新样本,我可以删除多对多关系,没有任何问题。请忽略命名约定,因为我将它们快速地放在一起进行测试。

订购实体

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实体

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

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


    }
}

这是配置文件

<?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中的表结构,以及将连接表外键列设置为Allow nulls。

Project Order Relationship diagram

测试结果

enter image description here

删除前,PROJECT_ORDER表中有3行

enter image description here

删除后只有一行

enter image description here