LINQ to SQL проверяет все поля, а не просто останавливает сначала ошибочное поле - PullRequest
1 голос
/ 10 августа 2009

Я только начал использовать классы LINQ to SQL, и мне действительно нравится, как это помогает мне писать читаемый код. В документации типичные примеры утверждают, что для пользовательской проверки вы создаете частичный класс следующим образом: *

partial class Customer 
{
    partial void OnCustomerIDChanging(string value)
    {
        if (value=="BADVALUE") throw new NotImplementedException("CustomerID Invalid");
    }
}

И аналогично для других полей ... А затем в коде позади я поместил что-то вроде этого, чтобы отобразить сообщение об ошибке и оставить пользователя на той же странице, чтобы исправить ошибку.

    public void CustomerListView_OnItemInserted(object sender, ListViewInsertedEventArgs e)
{
    string errorString = "";
    if (e.Exception != null)
    {
      e.KeepInInsertMode = true;
      errorString += e.Exception.Message;
      e.ExceptionHandled = true;
    }
    else errorString += "Successfully inserted Customer Data" + "\n";
    errorMessage.Text = errorString;
}

Хорошо, это просто, но тогда он прекращает проверять остальные поля, как только выдается первое Исключение !! Означает, что если пользователь сделал режим чем одна ошибка, он / он / она будет уведомлен только о первой ошибке. Есть ли другой способ проверить все входные данные и показать ошибки в каждом? Любые предложения приветствуются, спасибо.

Ответы [ 3 ]

1 голос
/ 04 февраля 2010

Это похоже на работу для блока приложения проверки библиотеки предприятия (VAB). VAB был разработан для возврата всех ошибок. Кроме того, он не выдает исключение, поэтому вы можете просто попросить его подтвердить тип для вас.

Когда вы решите использовать VAB, я советую вам не использовать методы LINX to SQL OnXXXChanging и OnValidate. Лучше переопределить метод SubmitChange (ConflictMode) в классе DataContext для вызова в API проверки VAB. Это исключает вашу логику проверки из ваших бизнес-сущностей, что делает ваши сущности чистыми.

Посмотрите на следующий пример:

public partial class NorthwindDataContext
{
    public ValidationResult[] Validate()
    {
        return invalidResults = (
            from entity in this.GetChangedEntities()
            let type = entity.GetType()
            let validator = ValidationFactory.CreateValidator(type)
            let results = validator.Validate(entity)
            where !results.IsValid
            from result in results
            select result).ToArray();            
    }

    public override void SubmitChanges(ConflictMode failureMode)
    {
        ValidationResult[] this.Validate();

        if (invalidResults.Length > 0)
        {
            // You should define this exception type
            throw new ValidationException(invalidResults);
        }

        base.SubmitChanges(failureMode);
    }

    private IEnumerable<object> GetChangedEntities()
    {
        ChangeSet changes = this.GetChangeSet();

        return changes.Inserts.Concat(changes.Updates);
    }
}

[Serializable]
public class ValidationException : Exception
{
    public ValidationException(IEnumerable<ValidationResult> results)
        : base("There are validation errors.")
    {
        this.Results = new ReadOnlyCollection<ValidationResult>(
            results.ToArray());
    }

    public ReadOnlyCollection<ValidationResult> Results
    {
        get; private set; 
    }
}

Вызов метода Validate () вернет коллекцию всех ошибок, но вместо вызова Validate () я бы просто вызвал SubmitChanges (), когда вы будете готовы к сохранению. SubmitChanges () теперь будет проверять ошибки и генерировать исключение, когда один из объектов недействителен. Поскольку список ошибок отправляется в ValidationException, вы можете перебирать ошибки выше стека вызовов и представлять их пользователю следующим образом:

try
{
    db.SubmitChanges();
}
catch (ValidationException vex)
{
    ShowErrors(vex.ValidationErrors);
}

private static void ShowErrors(IEnumerable<ValidationResult> errors)
{
    foreach(var error in errors)
    {
        Console.WriteLine("{0}: {1}", error.Key, error.message);
    }
}

Когда вы используете этот подход, убедитесь, что ваши сущности всегда проверены, прежде чем сохранять их в базе данных

Здесь - хорошая статья, объясняющая, как интегрировать VAB с LINQ to SQL. Вы обязательно должны прочитать его, если хотите использовать VAB с LINQ to SQL.

0 голосов
/ 10 августа 2009

Я понял это. Вместо того, чтобы выдавать исключение при первой неудачной проверке, я сохраняю сообщение об ошибке в классе со статической переменной. чтобы сделать это, я расширяю класс DataContext следующим образом: *

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

/// <summary>
/// Summary description for SalesClassesDataContext
/// </summary>
public partial class SalesClassesDataContext
{
    public class ErrorBox
    {
        private static List<string> Messages = new List<string>();
        public void addMessage(string message)
        {
            Messages.Add(message);
        }
        public List<string> getMessages() 
        {
            return Messages;
        }
    }
}

в классах, соответствующих каждой таблице, я бы унаследовал вновь определенный класс следующим образом:

public partial class Customer : SalesClassesDataContext.ErrorBox

только в функции OnValidate я бы выдал исключение в случае, если количество ошибок не равно 0. Следовательно, не пытаясь вставить и удерживать пользователя на той же странице ввода, не теряя введенные данные.

0 голосов
/ 10 августа 2009

Не с LINQ. Предположительно, вы бы проверили ввод перед , передав его LINQ.

То, что вы видите, - это естественное поведение с исключениями.

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