LINQ to SQL: OnValidate () и пользовательские классы модели домена - PullRequest
2 голосов
/ 20 сентября 2009

Работая с NerdDinner Tutorial , я пытаюсь найти хороший способ выполнить проверку свойств, которые не зависят от сгенерированного частичного класса LINQ-to-SQL. Вот пример кода того, что я сделал до сих пор:

public abstract class DomainEntity
{
    public IEnumerable<ValidationError> ValidationErrors { get; private set; }

    public bool Validate()
    {
        bool isValid = false;

        if (this.ValidationErrors != null)
            this.ValidationErrors = null;

        this.ValidationErrors = this.GetValidationErrors();

        if (this.ValidationErrors.Count() == 0)
            isValid = true;

        return isValid;
    }

    protected abstract IEnumerable<ValidationError> GetValidationErrors();
}

public partial class Email : DomainEntity
{
    protected override IEnumerable<ValidationError> GetValidationErrors()
    {
        if (!this.ValidateAddress())
            yield return new ValidationError("Address", DomainResources.EmailAddressValidationErrorMessage);

        yield break;
    }

    partial void OnValidate(ChangeAction action)
    {
        bool isValid = this.Validate();

        if (!isValid)
            throw new InvalidEmailException(this);
    }

    private bool ValidateAddress()
    {
        // TODO: Use a regex to validate the email address.

        return !string.IsNullOrEmpty(this.Address);
    }
}

Где Email - это сгенерированный тип LINQ-to-SQL, основанный на таблице Email. Поскольку таблица Email является лишь одним из нескольких объектов, связанных с классом модели домена (скажем, «Пользователь»), идеальным вариантом является создание класса модели домена «Пользователь» и использование атрибутов Application Validation Block для проверить свойства. Другими словами, я хотел бы использовать это:

public class User
{
    private Email emailEntity;

    [EmailAddressValidator]
    public string EmailAddress
    {
        get { return emailEntity.Address; }
        set { emailEntity.Address = value; }
    }
}

Так что, если я изменю свою схему базы данных, и эти изменения попадут в мои классы, сгенерированные LINQ-to-SQL, у меня не будет этих потерянных частичных классов (например, частичного класса Email). Я также хочу получить выгоду от интеграции атрибутов блока приложения проверки, чтобы мне не нужно было поддерживать коллекцию регулярных выражений, как это делается в руководстве NerdDinner. Кроме того, пользователь как класс домена будет функциональной единицей в домене, а не электронной почтой и другими объектами, для создания моделей представлений, рендеринга представлений и т. Д. Однако нет способа перехватить вызов проверки без выполнения чего-то вроде:

public abstract class DomainEntity
{
    public event EventHandler Validation(object sender, EventArgs args);
    protected void OnValidation()
    {
        if (this.Validate != null)
            this.Validate(this, EventArgs.Empty);
    }
}

public partial class Email
{
    partial void OnValidate(ChangeAction action)
    {
        this.OnValidation();
    }
}

И затем пользователь подключается к этому событию и обрабатывает все проверки внутри пользователя. Будет ли это хорошо работать с блоком приложения проверки? Как правильно выполнять проверку в классах агрегированных доменов, таких как «Пользователь»?

1 Ответ

1 голос
/ 29 сентября 2009

Рассматривайте валидацию как услугу, а не как ответственность субъекта, это позволит вам отделить реализацию валидации от определения того, что является валидным, и превратить валидацию в явную операцию, а не в неявную (управляемую L2S) .

Просмотрите правильную проверку правильности .net (http://www.codeplex.com/FluentValidation) для хорошей реализации этого подхода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...