我已经开始使用this扩展程序,只想说它非常好,谢谢!
现在我有一个问题,一个对象可以从一个集合移动到另一个集合,当我这样做时,我得到一个异常
InvalidOperationException:违反了多重性约束
我猜这是因为该对象未在原始集合中找到,并且此扩展将对象添加到新集合中,即使我希望它也被移动,然后在保存时,EF抛出异常,因为我有两个对象与我的上下文相同的键。
但是我怎么能让它发挥作用呢?
所以,如果我有以下对象结构
MyRoot
| Collection
| MyChild
| Collection
| MyObject (1)
| MyChild
| Collection
| MyObject (2)
如何将MyObject (1)
移动到与MyObject (2)
??
这些都是基本对象,这里有一些简单的代码
public class MyRoot
{
public int Id { get; set; }
public ICollection<MyChild> MyChildren { get; set; }
}
public class MyChild
{
public int Id { get; set; }
public int RootId { get; set; }
public MyRoot Root { get; set; }
public ICollection<MyObject> MyObjects { get; set; }
}
public class MyObject
{
public int Id { get; set; }
public string Name { get; set; }
public int ChildId { get; set; }
public MyChild Child { get; set; }
}
这些对象中的每一个都有一个DTO,为了这个例子,我们可以说对象完全相同,最后有扩展DTO(在实际应用中不是这种情况)
在我的应用程序中,我有一个自动收录器配置文件,如此
internal class MyProfile: Profile
{
public MyProfile()
{
this.CreateMap<MyRoot, MyRootDTO>()
.ReverseMap();
this.CreateMap<MyChild, MyChildDTO>()
.ReverseMap()
.EqualityComparison((s, d) => s.Id == d.Id);
this.CreateMap<MyObject, MyObjectDTO>()
.ReverseMap()
.EqualityComparison((s, d) => s.Id == d.Id);
}
}
在我的web api控制器方法上,我有这个,非常简单
public async Task<IActionResult> UpdateAsync([FromBody] MyRootDTO model)
{
// get the object and all children, using EF6
var entity = await _service.GetAsync(model.Id);
// map
_mapper.Map(model, entity);
// pass object now updated with DTO changes to save
await _service.UpdateAsync(entity);
// return
return new OkObjectResult(_mapper.Map<MyRootDTO>(entity));
}
如果有人可以请求帮助,那就太棒了!
答案 0 :(得分:0)
我不认为你的问题与AutoMapper有任何关系,这是一个实体框架问题。如果从EF中的子集合中删除某些内容,除非您在其上调用.Delete,或者该对象的键是包含父项的复合键,否则它不会自动删除。
我建议制作一个复合键,例如:
const collection = 'books';
db[collection].find()
public class MyObject
{
[Column(Order = 1)]
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
[Column(Order = 0)]
[Key]
public int ChildId { get; set; }
public MyChild Child { get; set; }
}
选项将[DatabaseGenerated]
列保留为标识 - EF的默认值与复合键不具有自动标识。
您可以在Id
实体上执行相同的操作。
答案 1 :(得分:0)
为了使其工作,我没有更改EF键,但在我的AutoMapper配置文件中实现了一个方法。我遍历该对象以查看该子项是否在不同的列表中,如果是,则将该对象移动到该新列表中。这样,automapper就能够基于ID来匹配对象。
我将以下代码添加到.BeforeMap
方法
在此示例中,不是我的基础对象被称为Root
,因此参数s
的类型为RootModel
(来自我的网络API),参数d
的类型为{ {1}}(来自EF)。 Root
和RootModel
都有一个名为Root
Sections