繁体   English   中英

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

[英]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.

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