Фрагменты кода, которые вы разместили, не поддаются никакому правдоподобному объяснению того, почему вы в конечном итоге получили бесконечный цикл. Я думаю, что this.alias
может быть свойством, в отличие от поля, которое подразумевает регистр символов, но нужно будет увидеть больше. Если это свойство, то вы вызываете метод OnAliasChanging
до того, как свойство будет установлено; следовательно, попытка установить его снова одним и тем же методом всегда приведет к бесконечному циклу. Обычно способ разработки этого сценария состоит в том, чтобы либо реализовать свойство Cancel
в производной OnXyzChanging
EventArgs
, либо сохранить старое значение в методе OnXyzChanging
, а затем выполнить проверку / откат в методе OnXyzChanged
если вы не можете использовать первый (лучший) вариант.
По сути, то, что вы пытаетесь сделать, это не очень хороший дизайн в целом и идет вразрез с принципами Linq to SQL, в частности. Предполагается, что сущность Linq to SQL - это POCO, не имеющая сведений об элементах-роднях или базовой базе данных. Для выполнения дуплексной проверки каждого изменения свойства требуется не только доступ к DataContext
или SqlConnection
, но и то, что технически можно назвать побочным эффектом (открытие нового соединения с базой данных и / или скрытое удаление свойства). менять). Такой дизайн просто кричит о таинственных авариях в будущем.
Фактически, ваш конкретный сценарий является одной из главных причин, по которым класс DataContext
был сделан расширяемым. Этот тип операции принадлежит там. Допустим, что сущность здесь называется User
с таблицей Users
.
partial class MyDataContext
{
public bool ChangeAlias(Guid userID, string newAlias)
{
User userToChange = Users.FirstOrDefault(u => u.ID == userID);
if ((userToChange == null) || Users.Any(u => u.Alias == newAlias))
{
return false;
}
userToChange.Alias = newAlias;
// Optional - remove if consumer will make additional changes
SubmitChanges();
return true;
}
}
Это инкапсулирует операцию, которую вы хотите выполнить, но не мешает потребителям напрямую изменять свойство Alias
. Если вы можете с этим смириться, я бы тут же остановился - у вас все равно должно быть УНИКАЛЬНОЕ ограничение в вашей базе данных, поэтому этот метод можно просто документировать и использовать как безопасный способ попытаться изменить имя, не рискуя позже нарушением ограничения (хотя всегда есть некоторый риск - у вас все еще может быть состояние гонки, если вы не поместите все это в транзакцию или хранимую процедуру).
Если вы абсолютно должны ограничить доступ к базовому свойству, один из способов сделать это - скрыть исходное свойство и создать оболочку только для чтения. В конструкторе Linq щелкните свойство Alias
и на листе свойств измените Access на Internal
и Name на AliasInternal
(но не коснитесь источника !). Наконец, создайте частичный класс для сущности (я бы сделал это в том же файле, что и частичный класс MyDataContext
) и напишите оболочку только для чтения для свойства:
partial class User
{
public string Alias
{
get { return AliasInternal; }
}
}
Вам также нужно обновить Alias
ссылки в нашем методе ChangeAlias
до AliasInternal
.
Имейте в виду, что это может нарушить запросы, которые пытаются фильтровать / группировать в новой оболочке Alias
(я думаю, Linq будет жаловаться, что не может найти сопоставление SQL). Само свойство будет нормально работать как средство доступа, но если вам нужно выполнить поиск на Alias
, то вам, вероятно, понадобится еще один вспомогательный метод GetUserByAlias
в MyDataContext
, который может выполнять «настоящий» запрос на AliasInternal
.
Вещи начинают становиться немного рискованными, когда вы решаете, что хотите связываться с логикой доступа к данным Linq в дополнение к логике домена, поэтому я рекомендую выше просто оставить свойство Alias
в покое и документ его использование соответствующим образом. Linq разработан для оптимистичного параллелизма; Обычно, когда вам нужно применить ограничение UNIQUE в вашем приложении, вы ждете, пока изменения действительно будут сохранены, и затем обрабатываете нарушение ограничения, если это произойдет. Если вы хотите сделать это немедленно, ваша задача усложняется, что и является причиной многословия и общей глупости.
Еще раз - я рекомендую против дополнительный шаг создания оболочки только для чтения; В любом случае, я добавил код на случай, если ваша спецификация по какой-то причине этого требует.