0

Alias というフィールドを持つ LINQ to SQL テーブルがあるとします。

次に、OnAliasChanging(string value); というメソッド スタブがあります。

私がやりたいことは、値を取得し、値が既に存在するかどうかをデータベースで確認してから、値を既に入力された値に設定することです。

したがって、エイリアスを「griegs」から「slappy」に変更している可能性があります。slappy が存在する場合は、既存の「griegs」の値に戻したいと考えています。

ので、私は持っています;

    partial void OnaliasChanging(string value)
    {
        string prevValue = this.alias;
        this.Changed = true;
    }

prevValue の値を確認すると、常に null です。

フィールドの現在の値を取得するにはどうすればよいですか?

アップデート

次のようなものを実装すると;

    partial void OnaliasChanging(string value)
    {
        if (this.alias != null)
            this.alias = "TEST VALUE";
    }

不健康な無限ループに入ります。

エイリアスが既に == "TEST VALUE" かどうかを確認するチェックを含めると、値は常に元の値であるため、無限ループが残ります。

これを行う方法はありますか?

4

2 に答える 2

1

投稿したコードスニペットは、無限ループに陥る理由についてのもっともらしい説明には役立ちません。文字のケーシングが意味するフィールドとは対照的に、それはプロパティかもしれないと思ってい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参照をに更新する必要があります。ChangeAliasAliasInternal

これにより、新しいラッパーでフィルター/グループ化しようとするクエリが破損する可能性があることに注意してくださいAlias(LinqはSQLマッピングが見つからないと文句を言うと思います)。プロパティ自体はアクセサーとして正常に機能しますが、でルックアップを実行する必要がある場合は、で「実際の」クエリを実行できるAlias別のGetUserByAliasヘルパーメソッドが必要になる可能性があります。MyDataContextAliasInternal

ドメインロジックに加えてLinqのデータアクセスロジックをいじりたいと思ったとき、物事は少し厄介になり始めます。そのため、プロパティをそのままにして、Aliasその使用法を適切に文書化することを上記でお勧めします。Linqは、楽観的同時実行性を中心に設計されています。通常、アプリケーションでUNIQUE制約を適用する必要がある場合は、変更が実際に保存されるまで待機し、変更が発生した場合は制約違反を処理します。すぐにやりたい場合は、タスクが難しくなります。これが、この冗長性と一般的なぎこちなさの理由です。

もう一度-読み取り専用ラッパーを作成するという追加の手順に反対することをお勧めします。あなたのスペックが何らかの理由でそれを必要とする場合に備えて、とにかく私はいくつかのコードを載せました。

于 2009-12-23T00:52:05.337 に答える
0

初期化中にOnaliasChangingが起動しているためにハングアップしているので、バッキングフィールド(エイリアス)は初期化されないため、常にnullになりますか?

これ以上の文脈がなければ、それは私にはそれがどのように聞こえるかです。

于 2009-12-23T00:33:01.687 に答える