none
主外表批量删除 当有外键存在时不允许删除出现异常,这个异常为什么会一直跟着上下文,不能让我继续下删 RRS feed

  • 问题

  • MVC4+entity framework5 (简称ef)

    业务:

    一个用户表,一个角色表,一个用户角色关联表(存放的是用户与角色的外键)。

    当我做级联删除时,主键为在外键使用的数据可以删除,如果已经被使用了那么我需要把被使用的主键表中的名称返回到前台,其他程序继续完成。

    现功能为想批量删除用户表信息,约束如下:

    一:当用户表中数据有外键在用户角色关联表中存在时,此条数据禁止删除,

    二:当用户表中主键在其他表中无任何外键使用时,此用户可以被删除。

    现问题:做批量删除时

    一、如批量删除的第一条记录符合约束二,第一条记录可以删除,但当继续连续删除时碰到行数据符合约束一时,ef上下文出现异常,致使当前行不可删除,那么我们可以不删当前行而继续下删,当时继续下删时,不管是否符合约束一还是约束二的都会把第一次出现的异常捕获到,致使符合约束二的信息也不可删除。

    请问如何把第一次的异常抛出或者清空,让删除继续下行。

    代码如下:

     public ActionResult DeleteActionInfo(string ID)
            {
                string message = "";//定义不可删除数据
                //定义List集合存放这些需要删除的数据
                List<string> list = new List<string>();
                for (int i = 7; i < 9; i++)
                {
                    tcdzswEntities _context = new tcdzswEntities();
                    try//捕获到当前信息删除失败(可能是因为有外键存在(因有外键做约束有外键存在时主键不可删除,而ef返回的不是true false  而是一个异常,所以用异常捕获,当出现异常时当前信息不可删除,但循环继续,可是问题是出现一个异常了,循环都在继续但是 每次  _context.Entry<USERINFO>(od).State = EntityState.Deleted;
                            _context.SaveChanges();  时 不管这条数据是否有外键存在都会把第一次出现的异常给捕获到 致使我能删的都不可以删了,这个问题怎么解决))
                    {
                        var dID = i.ToString();
                        var aa = LoadEntities(a => a.USERID == dID);
                        foreach (USERINFO od in aa)
                        {
                            _context.Set<USERINFO>().Attach(od);
                            _context.Entry<USERINFO>(od).State = EntityState.Deleted;
                            _context.SaveChanges();
                        }

                    }
                    catch
                    {
                        var dID = i.ToString();
                        var aa = LoadEntities(a => a.USERID == dID);
                        foreach (USERINFO od in aa)
                        {
                            message = message + od.LOGINNAME + ",";//不可删除数据拼接
                        }
                        _context.Dispose();
                    }
                }

    }

    2014年4月10日 23:59

答案

  • 对于你的需求,这种先Load出来,然后设置Delete再SaveChanges的方式有些啰嗦。

    我一直在用EF 6的Code First,忘了EF 5里怎样,建议你还是写一个存储过程一次性处理。存储过程大概是这样的:

    CREATE PROCEDURE spDelUser
        @UserId INT
    AS
    DELETE
    FROM UserInfo I
    WHERE UserId = @UserId 
        -- 忽略掉被用做外键的记录
        AND UserInfoId NOT IN (
            SELECT 1 
            FROM ForeignKeyTable
            WHERE UserInfoId = I.UserInfoId
        )
    然后用EF调用这个存储过程。这种做法相信无论是运行效率还是可读性都比较高。



    理解的越多,需要记忆的就越少


    2014年4月21日 7:48
    版主

全部回复

  • 不知道楼主为什么不在删除一条数据前做下check,确保其没有外键约束了之后,再删掉这笔数据库?用异常来check是否有约束存在,不推荐用这种方法。

    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2014年4月11日 9:28
    版主
  • 主要是 我 这里  约束手动判断可能要做上千次表查询 每个表就算只有20w数据 那么 速度也是很慢的  ,而走sql的自我主外键约束那么会很快很快

    2014年4月15日 7:39
  • 楼主用存储过程,应该会快点,但是我觉得还是需要去手动check是否有约束存在的。

    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2014年4月16日 6:13
    版主
  • 对于你的需求,这种先Load出来,然后设置Delete再SaveChanges的方式有些啰嗦。

    我一直在用EF 6的Code First,忘了EF 5里怎样,建议你还是写一个存储过程一次性处理。存储过程大概是这样的:

    CREATE PROCEDURE spDelUser
        @UserId INT
    AS
    DELETE
    FROM UserInfo I
    WHERE UserId = @UserId 
        -- 忽略掉被用做外键的记录
        AND UserInfoId NOT IN (
            SELECT 1 
            FROM ForeignKeyTable
            WHERE UserInfoId = I.UserInfoId
        )
    然后用EF调用这个存储过程。这种做法相信无论是运行效率还是可读性都比较高。



    理解的越多,需要记忆的就越少


    2014年4月21日 7:48
    版主
  • 对于你的需求,这种先Load出来,然后设置Delete再SaveChanges的方式有些啰嗦。

    我一直在用EF 6的Code First,忘了EF 5里怎样,建议你还是写一个存储过程一次性处理。存储过程大概是这样的:

    CREATE PROCEDURE spDelUser
        @UserId INT
    AS
    DELETE
    FROM UserInfo I
    WHERE UserId = @UserId 
        -- 忽略掉被用做外键的记录
        AND UserInfoId NOT IN (
            SELECT 1 
            FROM ForeignKeyTable
            WHERE UserInfoId = I.UserInfoId
        )
    然后用EF调用这个存储过程。这种做法相信无论是运行效率还是可读性都比较高。



    理解的越多,需要记忆的就越少


     谢谢 哥们 我后来的解决方案也是使用了存储过程, ef 是在是有好多地方不好用
    2014年4月24日 7:54