1

私はEFにまったく慣れていないので、まだ頭を抱えています.LINQ-SQLではなくストアドプロシージャを構築して呼び出すことに慣れているので、我慢してください!

他のエンティティに関連付けることができる単純なイメージ マネージャーを構築しようとしています。つまり、
Entity 1-has 1-> Image Collection-has many-> Images
Entity 2-has 1-> Image Collection-has many->Imagesなど...

現在、私は Image Collection -> Images 側のことをしようとしていますが、既存のデータを保存しようとすると、本当にイライラする問題に直面しています。
私のモデルではAddImage、コレクションalaの画像のリストにビジネスメソッドがあります

public class ImageCollection : Entity
{
    [Required]
    public string Title { get; set; }
    public virtual ICollection<Image> Images { get; set; }

    public void AddImage(Image Image)
    {
        this.Images.Add(Image);
    }
}

...そして、サービスがコレクションを更新します。これは、新しい画像を追加するときに問題ありません。

問題は情報の更新時です。これで、情報を関連付けている場合、次のような何らかのループに陥っている場合、既存のものに添付できることがわかりました。

// get tag from context
var image = new Image { Id = 1 } 

// attach into the entity
_service.Attach<Image>(image);

// attach image to collection
collection.Images.Add(image);

しかし、私がすでに画像を内部に持っている場合collection.Images、すべてを複製しようとせずに、コレクションをデータベースにコミット/保存するにはどうすればよいでしょうか? 付けてみた...

// attach any previously referenced images so they don't get duplicated
foreach (var image in Collection.Images.Where(image => image.Id > 0).ToList())
{
    Image i = new Image { Id = image.Id };
    (_imageCollectionRepository as GenericRespository<ImageCollection>).Attach<Image>(i);
}

状態を設定しようとしました(これは呼び出された内にありますSetAsUnchangedState<T>(T item){}

_context.Entry<T>(item).State = System.Data.EntityState.Unchanged;

しかし、何もありません。ただのエラー、An object with the same key already exists in the ObjectStateManagerまたはAcceptChanges cannot continue because the object’s key values conflict with another object in the ObjectStateManager.おそらく他のエラーです。

編集1。

私が現在行っている手順 - これが役立つ場合...

  1. コントローラーはImageCollectionエンティティを 受け取り、Imagesこの質問の上部にあるモデルのリストです。次に、ビューモデル (CollectionID および List) としてビューに送信されます。

  2. ビューには、これらの画像とそのプロパティ (タイトルのみ) が表示され、それが主キーです。その後、POSTされます。次に、コントローラーはサービスから画像コレクションを取得しImageCollection collection = _imageService.FindCollectionById(model.CollectionID)、ビジネス ロジックを介してビュー モデルに各画像を追加します。

  3. 次に、コントローラーはこの ImageCollection をサービスに渡して更新します。これは、コントローラーとビジネスロジックが永続性を無視する必要があるため、すべてが少し間違っていると思います-はい、コントローラーのIDによって現在ImageCollectionを取得していることを知っています! おそらく、ビュー モデルをサービスに渡すか、後でメッセージ リクエストを作成します。

EDIT 2 私は今、私が間違っていた場所を何とか解決しました. しかし、これはすべて本質的に正しいのでしょうか? または、これを行うより効率的な方法はありますか?

public void UpdateCollection(ViewModels.ImageCollectionViewModel model)
    {
        // get collection
        ImageCollection collection = FindCollectionById(model.CollectionID);

        if (model.Images != null)
        {
            GenericRespository<Image> temp_repository = new GenericRespository<Image>();

            // add images
            foreach (Image i in model.Images)
            {
                if (i.Id > 0)
                {
                    temp_repository.Attach<Image>(i);
                    temp_repository.Update(image);                        
                }
                else
                {
                    collection.Images.Add(i);
                }
            }

            temp_repository.SaveChanges();
        }

        _imageCollectionRepository.Update(collection);
        _imageCollectionRepository.SaveChanges();
    }

私はどこでそんなに間違っているのですか?:( ありがとう。

4

1 に答える 1

2

EF では、すべてのエンティティ オブジェクトに という識別子がありEntityKeyます (実行時に読み取り専用の値を確認できます)。たとえば、データベースから 10 個の画像を取得すると、これらのレコードのそれぞれに異なる一意のキーが割り当てられます。この EntityKey は、それらのレコードの ID として機能します。

新しいレコードを追加するとき、EntityKey は null です。これにより、DBcontext はこれが挿入されるレコードであることを認識できます。ただし、データベースから取得したレコードには EntityKey 値があります。

あなたの状況では(エラーメッセージに応じて)、既存のデータを(データベースデータと同じ主キーで)保存しようとしていますが、それらのentityKeyはnullです。この場合、DBcontextの新しいレコードと見なされますが、もちろん競合しますあなたのデータベースデータで。

エラーは、次のようなイメージ (またはリスト) をバインドする新しいイメージ (またはリスト) を作成していることが原因である可能性があります。

Image i = new Image { Id = image.Id };

これは正しくありません。代わりに使用

Image i = image ;

これが明確であることを願っています。

コメントに基づいて編集

アタッチ、既存のアイテムを取得するだけでなく、アタッチしたアイテムに基づいてそのプロパティを更新します。そのレベルで、アタッチする項目が DBContext に既に存在する場合 (これは EntityKeys を比較することによって行われます)、問題ありません。しかし、あなたの場合、null EntityKey を持つアイテムをアタッチしようとしています (その場合、アイテムは挿入されたアイテムと見なされます)。同時に、この挿入されたアイテムには、別のアイテムに対して既に存在する主キーがあります (これは技術的にはデータベース内の同じレコードですが、EntityKey が異なります)。

コードをデバッグし、項目を更新する前後にエンティティ キーをチェックして、値が変更されていないことを確認します。

ここに画像の説明を入力

于 2012-12-07T11:44:54.593 に答える