4

私は非常に大規模なプロジェクトをコーディングしており、EF4 とジョイナー テーブルの操作で問題が発生しました。

次の SQL テーブル定義があるとします。

CREATE TABLE [dbo].[SQLEntity](
    [Id] [bigint] IDENTITY(1,1) NOT NULL,
    [Field1] [nvarchar](128) NOT NULL,
    [Field2] [nvarchar] (256),
    [DateAdded] [datetime] NOT NULL,
    CONSTRAINT [PK_SQLEntity] PRIMARY KEY CLUSTERED ( 
        [Id] ASC 
    ) WITH (
        PAD_INDEX = OFF, 
        STATISTICS_NORECOMPUTE = OFF, 
        IGNORE_DUP_KEY = OFF, 
        ALLOW_ROW_LOCKS = ON, 
        ALLOW_PAGE_LOCKS = ON
    ) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

CREATE TABLE [dbo].[Util_LookupValues](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Description] [nvarchar](64) NOT NULL,
    CONSTRAINT [PK_Util_LookupValues] PRIMARY KEY CLUSTERED (
        [Id] ASC
    )WITH (
        PAD_INDEX = OFF, 
        STATISTICS_NORECOMPUTE  = OFF, 
        IGNORE_DUP_KEY = OFF, 
        ALLOW_ROW_LOCKS = ON, 
        ALLOW_PAGE_LOCKS  = ON
    ) ON [PRIMARY]
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[Xref_EntityValues](
    [SQLEntityId] [bigint] NOT NULL,
    [LookupId] [int] NOT NULL,
    CONSTRAINT [PK_Xref_PositionBenefits] PRIMARY KEY CLUSTERED (
        [SQLEntityId] ASC,
        [LookupId] ASC
    )WITH (
        PAD_INDEX = OFF, 
        STATISTICS_NORECOMPUTE = OFF, 
        IGNORE_DUP_KEY = OFF, 
        ALLOW_ROW_LOCKS = ON, 
        ALLOW_PAGE_LOCKS = ON
    ) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[Xref_EntityValues] WITH CHECK ADD CONSTRAINT [FK_Xref_EntityValues_Entity] FOREIGN KEY([SQLEntityId])
REFERENCES [dbo].[SQLEntity] ([Id])
GO

ALTER TABLE [dbo].[Xref_EntityValues] CHECK CONSTRAINT [FK_Xref_EntityValues_Entity]
GO

ALTER TABLE [dbo].[Xref_EntityValues]  WITH CHECK ADD  CONSTRAINT [FK_Xref_EntityValues_Util_LookupValues] FOREIGN KEY([LookupId])
REFERENCES [dbo].[Util_LookupValues] ([Id])
GO

ALTER TABLE [dbo].[Xref_EntityValues] CHECK CONSTRAINT [FK_Xref_EntityValues_Util_LookupValues]
GO

これらのテーブルに基づいてドメイン モデルが作成されると、SqlEntity と Util_LookupValues の 2 つのエンティティが作成されます。

この時点で、Util_LookupValues はルックアップ専用に値が定義されたテーブルです。Xref_EntityValues は、Entity オブジェクトをルックアップ値に結びつけるジョイナー テーブルであり、ルックアップ テーブルの「ルックアップ」機能を維持しながら、2 つの間に多対多の関係を持たせることができます。

Util_LookupValues の内容

Id   Description
---  ------------
1    Person
2    Car

ドメイン モデルに変更が加えられていない場合 (この質問では DataEntities と呼びます)、SQLEntity を PK が 1 と 2 の Util_LookupValues オブジェクトと結び付けるには、次のようにします。

IEnumerable<Util_LookupValues> lookupValues = DataEntities.Util_LookupValues.Where( lv => lv.Id == 1 || lv.Id == 2);

SQLEntity entity = new SQLEntity();
entity.Field1 = "some field";
entity.Field2 = "another field";
entity.DateAdded = DateTime.Now;

foreach(Util_LookupValues val in lookupValues)
{
    entity.Util_LookupValues.Add(val);     
}

DataEntities.SQLEntities.Add(entity);
DataEntities.SaveChanges();

ただし問題は、Xref_EntityValues に値を追加するだけでなく、このコードは 1 と 2 のコピーも新しいキーで Util_LookupValues に追加することです! 結果のデータベースは次のとおりです。

SQL Entity:
Id  Field1       Field2         DateAdded
-- -------      ------         ----------
1   some field  another field  04/04/2012

Xref_EntityValues:
SQLEntityId   LookupId
-----------   ---------
1              3
1              4

and Util_LookupValues:
Id   Description
---  ------------
1    Person
2    Car
3    Person
4    Car

Util_LookupValues には元のレコードが 2 つしかなく、Xref_EntityValues には適切な外部キーがあるようにするにはどうすればよいですか?

Xref_EntityValues:
SQLEntityId   LookupId
-----------   ---------
1              1
1              2

Util_LookupValues:
Id   Description
---  ------------
1    Person
2    Car
4

1 に答える 1

3

この線か…

IEnumerable<Util_LookupValues> lookupValues = DataEntities.Util_LookupValues
    .Where( lv => lv.Id == 1 || lv.Id == 2);

...そしてこの行...

DataEntities.SQLEntities.Add(entity);

...コンテキストの同じインスタンスを使用しますか? DataEntitiesあなたのコードスニペットはそれを示していますが、おそらくそれは「疑似コード」です。

インスタンスが異なる場合、エンティティの重複が発生します。はい。

したがって、次の 3 つのオプションがあります。

  • コンテキスト インスタンスが同じであることを確認してください。
  • Util_LookupValues返された を 2 番目のコンテキストにアタッチします。

    foreach(Util_LookupValues val in lookupValues)
    {
        DataEntities.Util_LookupValues.Attach(val);
        entity.Util_LookupValues.Add(val);     
    }
    
  • 最初のクエリはまったく実行しないでください。代わりに、「スタブ」エンティティを作成してアタッチします。

        var val = new Util_LookupValues { Id = 1 };
        DataEntities.Util_LookupValues.Attach(val);
        entity.Util_LookupValues.Add(val);     
    
        val = new Util_LookupValues { Id = 2 };
        DataEntities.Util_LookupValues.Attach(val);
        entity.Util_LookupValues.Add(val);     
    

    これが機能するのは、オブジェクトをコンテキストにアタッチして新しい関係を確立するときに、EF が知る必要があるのは主キー プロパティの値だけだからです。

于 2012-04-04T13:03:58.643 に答える