MVC5+EF多对多删除问题

u013618777 2016-08-11 10:28:59
几天已经沉醉在一个问题中了,现有一Material实体和Supplier实体,这两个表有个中间表(实体)MaterialWithSupplier。其中MaterialWithSupplier的结构为
        [Key]
[StringLength(150)]
public string Id { get; set; }
[ForeignKey("Material")]
public string MaterialNo { get; set; }
public virtual Material Material { get; set; }
[ForeignKey("Supplier")]
public int SupplierId { get; set; }
public virtual Supplier Supplier { get; set; }

在我想删除某个Material的时候,因为外键关联我要先删除MaterialWithSupplier,所以
                var MaterialWithSupplier = db.MaterialWithSuppliers.Where(m => m.MaterialNo == MaterialNo).ToList();
if (MaterialWithSupplier.Count > 0) db.MaterialWithSuppliers.Remove(MaterialWithSupplier[0]);
这样做了,但是这一操作把MaterialWithSupplier表中所有记录给删除了,我觉得很是奇怪,希望各位大大帮帮我,到底是啥原因啊?愁死我了!
...全文
242 12 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
u013618777 2016-08-13
  • 打赏
  • 举报
回复
事情到这也算是初步解决了,现在我已经把中间类替换为了FluentAPI形式了,找到删除所有记录的罪魁祸首:
modelBuilder.Entity<Material>().MapToStoredProcedures();
可是我看了下生成的迁移也没什么问题
            CreateStoredProcedure(
                "dbo.Material_Delete",
                p => new
                    {
                        MaterialNo = p.String(maxLength: 50, unicode: false, storeType: "nvarchar"),
                    },
                body:
                    @"DELETE FROM `t_material` WHERE `MaterialNo` = @MaterialNo;"
            );
,如果有谁知道希望能教小弟一下,在此谢过!当然,非常感谢楼上两位兄弟的热心帮助,尤其是@无Model不MVC!
u013618777 2016-08-13
  • 打赏
  • 举报
回复
引用 9 楼 dongxinxi 的回复:
EF默认是级联删除的,除非你手动关闭外键删除,并设置WillCascadeOnDelete(false)(或者在查出来Material后设置.MaterialWithSuppliers= null应该也可以) 当你需要级联删除时,还是像7#那样Include即可。
大哥,我按照你的做法,把中间类去掉了,现在是根据FluentAPI来关联,但是为啥我只删除一条数据,2个表(material,material_supplier)里所有的数据还是不见了呢?我真是快崩溃了
            var Material = db.Materials.Where(m => m.MaterialNo == MaterialNo).ToList();
            if (Material.Count == 0)
            {
                return "找不到該材料,可能已經被刪除!";
            }
            else
            {
                try
                {
                    db.Materials.Remove(Material[0]);
                    db.SaveChanges();
                }
u013618777 2016-08-12
  • 打赏
  • 举报
回复
引用 3 楼 qq_20324803 的回复:
调试呗。。。看看取到的数据是多少。看看删除的时候。那个tolist之后的数据集个数是多少。 不过,我看你ID用的是String类型???改成Int32吧。int型的。 代码我看没问题呢。调试一下就知道哪里出问题了。
感谢楼上,您说的我有做了,调试发现List里面只有一条记录,但是循环调用Remove或者一次调用RemoveRange方法以后MaterialWithSuppliers表中所有的记录都没了,很是奇怪!!!
摇撼大地 2016-08-12
  • 打赏
  • 举报
回复
调试呗。。。看看取到的数据是多少。看看删除的时候。那个tolist之后的数据集个数是多少。 不过,我看你ID用的是String类型???改成Int32吧。int型的。 代码我看没问题呢。调试一下就知道哪里出问题了。
u013618777 2016-08-12
  • 打赏
  • 举报
回复
anybody help!!?
u013618777 2016-08-12
  • 打赏
  • 举报
回复
像8#我做的那样我只是删除一条记录呀,就一定会把所有记录删除吗?为什么EF把所有的都删除了
  • 打赏
  • 举报
回复
EF默认是级联删除的,除非你手动关闭外键删除,并设置WillCascadeOnDelete(false)(或者在查出来Material后设置.MaterialWithSuppliers= null应该也可以) 当你需要级联删除时,还是像7#那样Include即可。
u013618777 2016-08-12
  • 打赏
  • 举报
回复
引用 5 楼 qq_20324803 的回复:
没遇到过这种情况。你调用saveChange没啊。调用的时候看看DbContext里面的表内容有多少。多对多表 里面的内容还有多少。在Save之前看看。
我也觉得很是奇怪,这个肯定是调用了SaveChanges了,不然不会处理数据的,我在想是不是多对多中间表表比较特殊呢还是怎么的
引用 7 楼 dongxinxi 的回复:
没什么特殊的,多对多其实拆开来就是两个方向的一对多 EF原则上是不直接处理关系表的 dbfirst,可以去外键那里启用级联删除,然后只需要删除主键纪录Material或者Supplier就行 codeFirst中则更直接,压根都不需要MaterialWithSuppliers这个关系实体类了,而且级联删除也不需要再去关心外键是否开启级联删除了,由EF来完成 用FluentAPI配置映射关系就是 this.HasRequired(m => m.Material) .WithMany(m => m.MaterialWithSuppliers) .HasForeignKey(m => m.MaterialNo) .WillCascadeOnDelete(true); Supplier同上 隐式 Material类 this.HasRequired(m => m.Supplier) .WithMany(m => m.Materials) .HasForeignKey(m => m.SupplierId) .WillCascadeOnDelete(true); Supplier类 this.HasRequired(m => m.Material) .WithMany(m => m.Supplier) .HasForeignKey(m => m.MaterialNo) .WillCascadeOnDelete(true); 当然也可以用HasMany().WithRequired().Map() 不管怎样,此时你都不再需要MaterialWithSuppliers这个类了 你的代码中没看到哪里有循环,看样子你是想删除Material和关联的MaterialWithSuppliers,如果级联删除没启用 你可以先将要删的东西全查出来 var material = db.Material.Include(m => m.MaterialWithSuppliers).Single(m => m.MaterialNo == MaterialNo); db.MaterialWithSuppliers.RemoveRange(material.MaterialWithSuppliers);这句不需要了 db.Material.Remove(material); db.SaveChanges();
非常感谢楼上,让我对EF理解加深了不少,按照你说的我加了级联,现在不用理会中间表直接删除Material,但是还是有个问题,现在我想删一条记录,结果是中间表和Material表里的所有数据都没了!!,代码如下:
            var Material = db.Materials.Where(m => m.MaterialNo == MaterialNo).ToList();
            if (Material.Count == 0)
            {
                return "找不到該材料,可能已經被刪除!";
            }
            else
            {
                try
                {
                    db.Materials.Remove(Material[0]);
                    db.SaveChanges();
                }
                catch (DataException/* dex */ e)
                {
                    //Log the error (uncomment dex variable name and add a line here to write a log.
                    return e.InnerException.InnerException.Message;
                }
还望大神能指导下!非常感激了!
  • 打赏
  • 举报
回复
没什么特殊的,多对多其实拆开来就是两个方向的一对多 EF原则上是不直接处理关系表的 dbfirst,可以去外键那里启用级联删除,然后只需要删除主键纪录Material或者Supplier就行 codeFirst中则更直接,压根都不需要MaterialWithSuppliers这个关系实体类了,而且级联删除也不需要再去关心外键是否开启级联删除了,由EF来完成 用FluentAPI配置映射关系就是 this.HasRequired(m => m.Material) .WithMany(m => m.MaterialWithSuppliers) .HasForeignKey(m => m.MaterialNo) .WillCascadeOnDelete(true); Supplier同上 隐式 Material类 this.HasRequired(m => m.Supplier) .WithMany(m => m.Materials) .HasForeignKey(m => m.SupplierId) .WillCascadeOnDelete(true); Supplier类 this.HasRequired(m => m.Material) .WithMany(m => m.Supplier) .HasForeignKey(m => m.MaterialNo) .WillCascadeOnDelete(true); 当然也可以用HasMany().WithRequired().Map() 不管怎样,此时你都不再需要MaterialWithSuppliers这个类了 你的代码中没看到哪里有循环,看样子你是想删除Material和关联的MaterialWithSuppliers,如果级联删除没启用 你可以先将要删的东西全查出来 var material = db.Material.Include(m => m.MaterialWithSuppliers).Single(m => m.MaterialNo == MaterialNo); db.MaterialWithSuppliers.RemoveRange(material.MaterialWithSuppliers);这句不需要了 db.Material.Remove(material); db.SaveChanges();
u013618777 2016-08-12
  • 打赏
  • 举报
回复
引用 5 楼 qq_20324803 的回复:
没遇到过这种情况。你调用saveChange没啊。调用的时候看看DbContext里面的表内容有多少。多对多表 里面的内容还有多少。在Save之前看看。
我也觉得很是奇怪,这个肯定是调用了SaveChanges了,不然不会处理数据的,我在想是不是多对多中间表表比较特殊呢还是怎么的
摇撼大地 2016-08-12
  • 打赏
  • 举报
回复
没遇到过这种情况。你调用saveChange没啊。调用的时候看看DbContext里面的表内容有多少。多对多表 里面的内容还有多少。在Save之前看看。
u013618777 2016-08-11
  • 打赏
  • 举报
回复
顶一下!!!!

111,094

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧