私は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。
私が現在行っている手順 - これが役立つ場合...
コントローラーは
ImageCollection
エンティティを 受け取り、Images
この質問の上部にあるモデルのリストです。次に、ビューモデル (CollectionID および List) としてビューに送信されます。ビューには、これらの画像とそのプロパティ (タイトルのみ) が表示され、それが主キーです。その後、POSTされます。次に、コントローラーはサービスから画像コレクションを取得し
ImageCollection collection = _imageService.FindCollectionById(model.CollectionID)
、ビジネス ロジックを介してビュー モデルに各画像を追加します。次に、コントローラーはこの 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();
}
私はどこでそんなに間違っているのですか?:( ありがとう。