问题
I've got a class User which has an attribute Name that must be unique. So far I've investigated 3 ways of checking this:
Annotations
[StringLength(100)] [Index(IsUnique = true)] public string Name { get; set; }
Problem is, by trying to insert a user with a repeated name it throws this ex: as you can see, I would have to navigate into the inner exceptions (which I don´t know if it is possible, but I assume it is) and the last inner exception´s message is not user friendly at all.
- Fluent Api
https://stackoverflow.com/a/23155759/5750078
I haven´t tried it but I believe it is has the same problem that Annotations.
- Check by hand
controller code:
[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);
}
Problem: the check depends on my code, which may not be as accurate as date base checkings. Besides I will need to program more logic than the other two options. And last but no least if somehow I access the database directly there will be no checks at all.
I need to know which is the best practice to do this, because I'm trying to learn on my own, and I would like to do things as best as possible.
回答1:
You should actually do both, a check in code and a uniqueness index as a final guard when concurrent users manage to insert identical records after all. (Because of the latency between the check and the actual insert).
This means that you always have to catch exceptions when you call SaveChanges
, but that's not a bad idea anyway.
For the uniqueness check you could use the mechanism I described here, just change email
into Name
and you're good to go.
You could dig up the last exception message from a chain of inner exceptions by this extension method:
public static string GetDeepestExceptionMessage(this Exception exception)
{
string msg = string.Empty;
while (exception != null)
{
msg = exception.Message;
exception = exception.InnerException;
}
return msg;
}
来源:https://stackoverflow.com/questions/41536964/best-way-to-control-unicity-of-an-attribute-using-ef-code-first