使用 EF Code First 控制属性唯一性的最佳方法

Posted

技术标签:

【中文标题】使用 EF Code First 控制属性唯一性的最佳方法【英文标题】:Best way to control unicity of an attribute using EF Code First 【发布时间】:2017-05-23 01:28:44 【问题描述】:

我有一个类 User,它的属性 Name 必须是唯一的。 到目前为止,我已经研究了 3 种检查方法:

注释

[StringLength(100)]
[Index(IsUnique = true)]
public string Name  get; set; 

问题是,通过尝试插入具有重复名称的用户,它会抛出这个 ex: 如您所见,我将不得不导航到内部异常(我不知道这是否可能,但我认为它是可能的)并且最后一个内部异常的消息根本不是用户友好的。

流利的API

https://***.com/a/23155759/5750078

我没试过,但我相信它和 Annotations 有同样的问题。

手动检查

控制器代码:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "Name,Password,Profile")] User user)
    
        if (ModelState.IsValid)
        
            lock (locker)
            
                validateNameUnicity();
                db.Users.Add(user);
                db.SaveChanges();
            
            return RedirectToAction("Index");
        

        return View(user);
    

问题:检查取决于我的代码,这可能不如基于日期的检查准确。此外,我需要编写比其他两个选项更多的逻辑。最后但同样重要的是,如果我以某种方式直接访问数据库,则根本不会进行任何检查。

我需要知道这样做的最佳做法是什么,因为我正在努力自学,并且我希望尽可能做到最好。

【问题讨论】:

【参考方案1】:

实际上,您应该同时做两个,检查代码唯一性索引作为最终保护,当并发用户最终设法插入相同的记录时。 (因为检查和实际插入之间的延迟)。

这意味着当您调用SaveChanges 时,您总是必须捕获异常,但无论如何这不是一个坏主意。

对于唯一性检查,您可以使用我描述的here 机制,只需将email 更改为Name 即可。

您可以通过此扩展方法从内部异常链中挖掘出最后一条异常消息:

public static string GetDeepestExceptionMessage(this Exception exception)

    string msg = string.Empty;
    while (exception != null)
    
        msg = exception.Message;
        exception = exception.InnerException;
    
    return msg;

【讨论】:

以上是关于使用 EF Code First 控制属性唯一性的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

在使用 EF 4.1 Code-First 的 Include 和/或 Select 方法时订购导航属性?

EF 4.1 中使用 Code First 的 ComplexType 集合属性

EF 4.1:使用 Fluent 映射从 Code First 中查找关键属性类型

EF Code First学习

EF Code First CTP5 - 使用属性名称作为外键的列名

EF4 CTP5 Code First 方法忽略表属性