0

私のデータモデルでは、オブジェクト/テーブル/データ間でかなり一般的な区分があります。

  • システムによって実行されている作業を表す「トランザクション」エンティティ。これらのエンティティはシステムによって作成され、特定のコンテキストでのみ重要です。それらは定期的にその場で作成されます。(余談ですが、このタイプのエンティティには適切な名前がありますか?)
  • トランザクションエンティティの共通プロパティを表す「データディクショナリ」エンティティ。これらは不規則に定義され(主にプロジェクトの開始時に)、はるかに静的なライフサイクルを持っています。それらは通常私によって作成されます。

したがって、たとえば、User(トランザクション)エンティティとUserType(データディクショナリ)エンティティがあるとします。

データディクショナリエンティティのインスタンスへの参照をコードに(ハード)コード化したい。これにより、理解しやすい言語でビジネスロジックをコーディングできるようになります。(たとえば、UserTypeが「Plain」でUserTypeが「Admin」で、「ユーザーのUserTypeがAdminと等しい場合にのみアクセスを許可する」というルールがあるとします)。

データアクセステクノロジ/ORMとしてLINQ-to-Entitiesを使用しています。データディクショナリ参照を実装するために、EntityKeysを保存しています。私の理解では、それらはオブジェクトコンテキストから切り離されているため、この目的に適しています。(エンティティの状態が含まれていないため、その状態が古くなることを心配する必要もありません。)

ただし、DD-EntityKey-referenceを使用して新しいトランザクションエンティティを追加しようとすると、問題が発生します。私の例を続けて、私はこれをやっています:

UserEntities userEntities = new UserEntitites()
User user = new User()
user.UserType = new UserType()
user.UserType.EntityKey = adminEntityKey
userEntities.AddToUser(user)

...そしてこれは私に次のエラーを与えます:

System.InvalidOperationException:オブジェクトにはすでにEntityKeyがあるため、オブジェクトをObjectStateManagerに追加できません。ObjectContext.Attachを使用して、既存のキーを持つオブジェクトをアタッチします。

AddToUserの代わりにuserEntities.Attach(user)を呼び出そうとすると、次のようになります。

System.InvalidOperationException:EntityKey値がnullのオブジェクトは、オブジェクトコンテキストにアタッチできません。

私が行っている新しいエンティティと既存のエンティティが混在していることを考えると、これらのエラーは両方とも理にかなっています。私がよくわからないのは、この問題を回避する方法です。DDエンティティの状態全体をロードしなくても、DDエンティティへの参照を切り離して、それらを新しいアタッチされたオブジェクトに割り当てる方法はありますか?

4

1 に答える 1

1

なぜこれらの例外が発生するのかを説明しようと思います。

System.InvalidOperationException:オブジェクトにはすでにEntityKeyがあるため、オブジェクトをObjectStateManagerに追加できません。ObjectContext.Attachを使用して、既存のキーを持つオブジェクトをアタッチします。

新しいUserエンティティとUserTypeエンティティが作成されます。UserTypeのEntityKeyは設定されていますが、userEntities.Add()に渡すと、EFはそれらのステータスをADDEDに設定しようとします。UserTypeにはEntityKeyが含まれているため、EFは何かが間違っていることに気づき、例外をスローします。

System.InvalidOperationException:EntityKey値がnullのオブジェクトは、オブジェクトコンテキストにアタッチできません。

この例外では、UserTypeですべて問題ありませんが、Userエンティティのために例外がスローされます-EntityKeyがないため、アタッチできません。

これが私がこの問題を解決する方法です(あなたが言うように、データディクショナリ参照のハードコーディングが問題ない場合):

UserTypeエンティティで、UserTypeIDへの静的参照を作成します。

public partial class UserType
    {
        public const int AdminUserTypeID = 1;
        public const int PlainUserTypeID = 2;
    }  

Userエンティティには、UserType外部キーに簡単にアクセスするためのエクステンダープロパティがあります。

public partial class User
{
    public int? UserTypeID
    {
        set
        {
           UserTypeReference.EntityKey = new EntityKey("UserEntities.UserType", "UserTypeID", value);
        }
        get
        {
            if (UserTypeReference.EntityKey == null)
                return null;

            if (UserTypeReference.EntityKey.EntityKeyValues.Count() > 0)
                return (int)UserTypeReference.EntityKey.EntityKeyValues[0].Value;
            else
                return null;
        }
    }
}

最後に、新しいユーザーを作成するためのユースケースは次のようになります。

using(UserEntities userEntities = new UserEntitites())
{
    User user = new User();
    user.UserTypeID = UserType.AdminUserTypeID;
    userEntities.AddToUser(user);
    userEntities.SaveChanges()
}
于 2009-10-27T08:46:20.240 に答える