Ibr*_*eem 11 entity-framework dto automapper navigation-properties asp.net-web-api
我有使用Entity Framework 5持久化的POCO域实体.它们是使用存储库模式从DbContext获得的,并通过UoW模式暴露给RESTful MVC WebApi应用程序.POCO实体是代理并且是延迟加载的.
我将我的实体转换为DTO,然后再将它们发送给客户端.我正在使用Automapper执行此操作,它似乎可以正常工作,Automapper将代理POCO映射到DTO,保持导航属性不变.我正在使用以下映射:
Mapper.CreateMap<Client, ClientDto>();
Run Code Online (Sandbox Code Playgroud)
域/ DTO对象的示例:
[Serializable]
public class Client : IEntity
{
public int Id { get; set; }
[Required, MaxLength(100)]
public virtual string Name { get; set; }
public virtual ICollection<ClientLocation> ClientLocations { get; set; }
public virtual ICollection<ComplianceRequirement> DefaultComplianceRequirements { get; set; }
public virtual ICollection<Note> Notes { get; set; }
}
public class ClientDto : DtoBase
{
public int Id { get; set; }
[Required, MaxLength(100)]
public string Name { get; set; }
public ICollection<ClientLocation> ClientLocations { get; set; }
public ICollection<ComplianceRequirementDto> DefaultComplianceRequirements { get; set; }
public ICollection<Note> Notes { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
现在我正在尝试使用从线路发回的DTO更新我的上下文.我在使导航属性/相关实体正常工作方面遇到了特殊问题.我正在使用的映射是:
Mapper.CreateMap<ClientDto, Client>()
.ConstructUsing((Func<ClientDto, Client>)(c => clientUow.Get(c.Id)));
Run Code Online (Sandbox Code Playgroud)
在上面,clientUow.Get()引用DbContext.Set.Find(),以便从EF获取跟踪的代理POCO对象(其中包含所有相关实体也作为代理).
在我的控制器方法中,我正在执行以下操作:
var client = Mapper.Map<ClientDto, Client>(clientDto);
uow.Update(client);
Run Code Online (Sandbox Code Playgroud)
客户端成功映射,作为代理POCO对象,但是它的相关实体/导航属性被替换为具有从DTO复制的属性值的新(非代理)POCO实体.
上面,uow.Update()基本上是指一个执行持久化逻辑的函数,我有:
_context.Entry<T>(entity).State = System.Data.EntityState.Modified;
_context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
上述内容甚至不会持续存在,更不用说相关实体了.我已经尝试了映射的变体和持久使用分离/状态的不同方法,但总是得到"具有相同键的对象已经存在于ObjectStateManager"异常中.
我已经看过无数其他线程,并且无法使用Automapper完成所有工作.我可以从上下文中获取代理对象并手动浏览属性,从DTO中更新它们,但是我使用Automapper来映射域 - > DTO,使用它来执行相反操作会更加优雅,因为我的DTO在很大程度上类似于我的域对象.
是否有教科书使用EF处理Automapper的方法,其中Domain Objects/DTO具有导航属性,同时还需要更新?
更新:
var originalEntity = _entities.Find(entity.Id);
_context.Entry<T>(originalEntity).State = System.Data.EntityState.Detached;
_context.Entry<T>(entity).State = System.Data.EntityState.Modified;
Run Code Online (Sandbox Code Playgroud)
上述持久性逻辑更新上下文中的"根"EF代理对象,但不更新任何相关实体.我猜这是因为它们没有映射到EF代理对象而是映射到纯域对象.帮助将非常感谢!
更新: 似乎我试图实现的目标实际上不可能使用当前版本的EF(5),这是EF的核心限制,与Automapper无关:
我想这是回归手动.希望这可以帮助那些想知道同样的人.
您已经确定了问题所在:
上述持久化逻辑更新上下文中的“根”EF 代理对象,但是任何相关实体都不会更新
您仅在根节点上设置修改状态。您必须编写代码来迭代所有对象并将状态设置为已修改。
| 归档时间: |
|
| 查看次数: |
6186 次 |
| 最近记录: |