Добавление предложения where по умолчанию в таблицу linq-to-sql

Можно ли добавить предложение where по умолчанию к каждому оператору SQL, сгенерированному классом Linq-to-SQL?

У меня есть собственный DataContext с классом Customer. Класс Customer имеет атрибут Deleted, и я хочу, чтобы он всегда был NULL всякий раз, когда я запрашиваю таблицу.

Так, например, я мог бы написать:

List<Customer> customers = db.Customers.ToList<Customer>();

Но реально получить:

List<Customer> customers = db.Customers.Where(o => o.Deleted == null).ToList<Customer>();

Я хочу сохранить «удаленные» данные в своей БД, но мне никогда не понадобится их видеть в моем коде .NET. Такой вид по умолчанию был бы удобен, поэтому мне не нужно помнить о добавлении фильтра к каждому запросу.


person Paul    schedule 21.09.2012    source источник
comment
Вместо добавления таблицы в конструктор dbml добавьте представление, содержащее предложение where по умолчанию, и просто назовите представление Customer в dbml.   -  person hatchet - done with SOverflow    schedule 21.09.2012
comment
см. ответ, который я добавил. Я включил информацию об обновлениях.   -  person hatchet - done with SOverflow    schedule 22.09.2012


Ответы (2)


Вместо добавления таблицы в конструктор dbml добавьте представление, содержащее предложение where по умолчанию, и просто назовите представление Customer в dbml.

Чтобы разрешить обновления, вставки и удаления, обязательно выберите столбцы первичного ключа в конструкторе DBML и пометьте их свойство Primary Key как true.

person hatchet - done with SOverflow    schedule 21.09.2012
comment
После еще нескольких тестов я действительно могу выполнять вставки и обновления просто отлично, за исключением случаев, когда я пытаюсь обновить поле «Удалено». Я получаю ChangeConflictException - Row not found or changed., когда звоню SubmitChanges(). Я предполагаю, что это связано с тем, что он просматривает представление, которое не содержит этой записи, поскольку Deleted больше не является null в моем сознании DataContext. - person Paul; 22.09.2012
comment
Нашел проблему. Мне пришлось изменить вычисляемые столбцы с AutoSync=Always на AutoSync=Never. - person Paul; 22.09.2012

Вы можете добавить новое свойство с именем ActiveCustomers, которое возвращает это:

public IQueryable<Customer> ActiveCustomers {
    get { return db.Customers.Where(e => e.Deleted == null); }
}

Любые запросы к этому свойству могут указывать дополнительные Where условия и иным образом изменять результаты, но они всегда будут начинаться с клиентов, которые не были удалены. И из-за отложенного выполнения LINQ этот оператор не вызывает выполнения каких-либо дополнительных запросов.

Если вам нужно убедиться, что никто не может получить доступ к db.Customers, вы можете попытаться скрыть его, выполнив что-то вроде этого (может не сработать, мне нужно увидеть вашу реализацию):

public new IQueryable<Customer> Customers {
    get {
      throw new InvalidOperationException("Use property ActiveCustomers instead.");
    }
}
person Yuck    schedule 21.09.2012
comment
Проблема с этим решением заключается в том, что когда я создаю new IQueryable<Customer> Customers, я получаю ошибку неоднозначности между этим и исходными клиентами, которые возвращают System.Linq.Table<Customer>. Но я не могу удалить оригинал, потому что тогда мои вызовы InsertOnSubmit терпят неудачу, поскольку он пытается выполнить это с IQueryable. - person Paul; 21.09.2012
comment
@Paul Если вы используете реализацию шаблона репозитория, вам все равно не следует запрашивать напрямую контекст. - person Yuck; 22.09.2012