为了账号安全,请及时绑定邮箱和手机立即绑定

使用重复的主键检测插入

使用重复的主键检测插入

C#
慕哥9229398 2021-07-06 17:04:25
我的 api 允许尝试添加具有相同主键的实体。但是,我想过滤由于这个原因而发生的 DbUpdateException,因为它们只会污染我的日志文件。我在生产中使用 Sqlite 进行测试和 Postgres,所以我想要一种可以返回一些异常类型以获取原因的方法。
查看完整描述

3 回答

?
慕雪6442864

TA贡献1812条经验 获得超5个赞

对于 Sql Server,您可以使用SqlException.Numberof 的内部异常的属性DbUpdateException来识别Violation of PRIMARY KEY错误。对于主键冲突 SqlException.Number = 2627。你可以尝试这样的事情:


try

{

    db.SaveChanges();

}

catch (DbUpdateException ex)

{

    if (ex.InnerException is SqlException sqlEx && sqlEx.Number == 2627)

    {

    }

}

我相信 forSqlite和Postgres想法应该是一样的


查看完整回答
反对 回复 2021-07-18
?
胡子哥哥

TA贡献1825条经验 获得超6个赞

我最终得到了一些 DbUpdateException 的扩展类,但仍然有点hacky:


public static class UpdateExceptionHelper

{

    public enum UpdateExceptionKind

    {

        UniqueViolation,

        ForeignKeyViolation,

        Unknown

    }


    public static UpdateExceptionKind Kind(this DbUpdateException dbUpdateException)

    {

        var inner = dbUpdateException.InnerException;

        switch (inner)

        {

            case null:

                return UpdateExceptionKind.Unknown;

            case SqliteException sqlite:

                return sqlite.Kind();

            case PostgresException postgres:

                return postgres.Kind();

            default:

                throw new Exception($"Unsupported Database Provider with Exception Type: {inner.GetType().Name}");



        }

    }


    private static UpdateExceptionKind Kind(this PostgresException e)

    {

        const string UNIQUE_VIOLATION = "23505";

        const  string FOREIGN_KEY_VIOLATION = "23503";


        switch (e.SqlState)

        {

            case UNIQUE_VIOLATION:

                return UpdateExceptionKind.UniqueViolation;

            case FOREIGN_KEY_VIOLATION:

                return UpdateExceptionKind.ForeignKeyViolation;

            default:

                return UpdateExceptionKind.Unknown;

        }

    }


    private static UpdateExceptionKind Kind(this SqliteException e)

    {

        const int SQLITE_CONSTRAINT_UNIQUE = 2067;

        const int SQLITE_CONSTRAINT_PRIMARYKEY = 1555;

        const int SQLITE_CONSTRAINT_FOREIGNKEY = 787;


        switch (e.SqliteExtendedErrorCode)

        {

            case SQLITE_CONSTRAINT_PRIMARYKEY:

            case SQLITE_CONSTRAINT_UNIQUE:

                return UpdateExceptionKind.UniqueViolation;

            case SQLITE_CONSTRAINT_FOREIGNKEY:

                return UpdateExceptionKind.ForeignKeyViolation;

            default:

                return UpdateExceptionKind.Unknown;

        }

    }

}


查看完整回答
反对 回复 2021-07-18
  • 3 回答
  • 0 关注
  • 332 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信