Я хотел бы уточнить ответ Стивена Клири. Он прав в использовании частичного класса / методов для обработки бизнес-правил в EF. Однако он не вдавался в подробности о том, что делать в этом частичном классе / методе. Я создал службу сокращения URL в своем блоге, чтобы использовать в качестве примера для этого. Моя сущность ShortURL
имеет только два столбца / свойства. Url
и ID
.
Я хотел проверить, что сокращенный URL-адрес является действительным URL-адресом, прежде чем он фактически сохранит его в базе данных через EF. Итак, я создал частичный класс и метод следующим образом:
public partial class ShortURL
{
partial void OnUrlChanging(string url)
{
if (!Regex.IsMatch(url, @"(^((http|ftp|https):\/\/|www\.)[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)"))
throw new Exception("Not a valid URL.");
}
}
Это остановило EF от изменения свойства, оставив его NULL. Но это все, что он сделал. Это не дало мне простой способ получить сообщение об ошибке и отобразить его пользователю (о котором я знаю РЕДАКТИРОВАТЬ: Согласно http://www.sellsbrothers.com/posts/Details/12700 IDataErrorInfo - единственный способ получить сообщение об ошибке для правильного отображения в ASP.NET MVC), поэтому я последовал другому примеру, который нашел где-то в темных уголках сети, и сделал свой частичный класс наследующим от IDataErrorInfo
. Затем я реализовал интерфейс и включил объект частного словаря для хранения сообщений об ошибках.
public partial class ShortURL : IDataErrorInfo
{
private Dictionary<string, string> errors = new Dictionary<string, string>();
partial void OnUrlChanging(string url)
{
if (!Regex.IsMatch(url, @"(^((http|ftp|https):\/\/|www\.)[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)"))
errors.Add("Url", "Not a valid URL.");
}
public string Error
{
get { return string.Empty; } //I never use this so I just return empty.
}
public string this[string columnName]
{
get
{
if (errors.ContainsKey(columnName))
return errors[columnName];
return string.Empty; //Return empty if no error in dictionary.
}
}
}
Теперь у меня есть полностью функциональный способ хранения, извлечения и отображения сообщений об ошибках. Теперь снова в моем контроллере (в MVC) я могу сделать if (!ModelState.IsValid)
[HttpPost]
public ViewResult URLShortener(ShortURL shortURL)
{
if (!ModelState.IsValid)
return View();
shortURL.Url = shortURL.Url.ToLower().StartsWith("www.") ? "http://" + shortURL.Url : shortURL.Url;
shortURLRepository.AddShortURL(shortURL);
object model = "http://www.u413.com/" + ShortCodes.LongToShortCode(shortURL.UrlID);
//Not related to this answer but I had to cast my string as a generic object because the View() method has a (string, string) constructor that does something totally different. My view actually uses string as the model. I know I know, I could have just used ViewBag.
return View("ShowUrl", model);
}
Вот и ты. Рабочий пример того, как расширить не только частичные методы EF, но и как распространить валидацию обратно в пользовательский интерфейс. Дайте мне знать, если что-то нуждается в улучшении или я что-то пропустил.