投稿したコードスニペットは、無限ループに陥る理由についてのもっともらしい説明には役立ちません。文字のケーシングが意味するフィールドとは対照的に、それはプロパティかもしれないと思っていthis.alias
ますが、もっと見る必要があります。プロパティの場合は、OnAliasChanging
プロパティが設定される前にメソッドを呼び出しています。したがって、同じメソッドで再度設定しようとすると、常に無限ループが発生します。通常、このシナリオを設計する方法はCancel
、導関数にプロパティを実装するかOnXyzChanging
EventArgs
、メソッドに古い値を保存してから、最初の(より良い)オプションを使用できない場合OnXyzChanging
はメソッドでチェック/ロールバックを実行することです。OnXyzChanged
ただし、基本的に、あなたがやろうとしていることは、一般的にあまり良い設計ではなく、特にLinqtoSQLの原則に反します。Linq to SQLエンティティは、兄弟エンティティや基盤となるデータベースをまったく認識していないPOCOであると想定されています。すべてのプロパティ変更に対して重複チェックを実行するには、DataContext
またはSqlConnection
にアクセスする必要があるだけでなく、技術的には副作用と呼ばれる可能性のあるもの(新しいデータベース接続を開く、および/またはプロパティ変更をサイレントに破棄する)も発生します。この種のデザインは、将来の不思議な衝突を叫ぶだけです。
DataContext
実際、あなたの特定のシナリオは、クラスが最初に拡張可能になった主な理由の1つです。このタイプの操作はそこに属します。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
これにより、実行する操作がカプセル化されますが、コンシューマーがプロパティを直接 変更することを妨げることはありません。これに耐えられるのであれば、そこで停止します。データベース自体にUNIQUE制約があるはずなので、このメソッドを文書化して、後で制約違反のリスクを冒すことなく名前変更を試みる安全な方法として使用できます。オン(常にある程度のリスクがありますが、これをすべてトランザクションまたはストアドプロシージャに入れない限り、競合状態が発生する可能性があります)。
基になるプロパティへのアクセスをどうしても制限する必要がある場合、これを行う1つの方法は、元のプロパティを非表示にして、読み取り専用ラッパーを作成することです。Linqデザイナで、プロパティをクリックしAlias
、プロパティシートで、 [アクセスInternal
]と[名前]をに変更します(ただし、[ソース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制約を適用する必要がある場合は、変更が実際に保存されるまで待機し、変更が発生した場合は制約違反を処理します。すぐにやりたい場合は、タスクが難しくなります。これが、この冗長性と一般的なぎこちなさの理由です。
もう一度-読み取り専用ラッパーを作成するという追加の手順に反対することをお勧めします。あなたのスペックが何らかの理由でそれを必要とする場合に備えて、とにかく私はいくつかのコードを載せました。