c# - 使用 automapper 更新 Entity Framework 实体

标签 c# entity-framework entity-framework-4 automapper

我正在尝试使用 Entity Framework 并让 Automapper 从我的契约(Contract)中更新我的实体。

我的代码是这样的:

var temp = OrderContract;
Order order = dataAccess.FindOne<Order>(x => x.OrderId == temp.OrderId) 
              ?? new Order();

Mapper.Map(OrderContract, order);

if (order.OrderId <= 0)
   dataAccess.Add(order);

(注意:我正在使用存储库模式。dataAccess.FindOne 调用 CreateQuery 以返回一个实体。)

我遇到的问题是人际关系。我在进行更新时遇到此错误(插入工作正常):

The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.

我猜 automapper 没有按照我想要的方式更新。根据错误消息和谷歌搜索,我推测我的集合关系(甚至可能不是集合的关系)正在由 Automapper 重新创建。

我如何告诉 Automapper 只更新而不重新制作任何对象或集合?

猜测:

我读到也许我需要为自动映射器使用 UseDestinationValue 选项。我回去把它放在我所有的收藏中,但是当我这样做时,我的插入会因外键违规而失败。

代码映射:

仅在一个集合上使用 UseDestinationValue(这个插入但不会更新):

//+ Source
Mapper.CreateMap<SourceContract, Source>()
    .IgnoreAllNonExisting();

//+ SelectedRequirement
Mapper.CreateMap<SelectedRequirementContract, SelectedRequirement>()
    .ForMember(x => x.SelectedRequirementId, opt => opt.MapFrom(src => src.RequirementId))
    .IgnoreAllNonExisting();

//+ Comment Contract
Mapper.CreateMap<CommentContract, Comment>()
    .ForMember(x => x.CommentText, opt => opt.MapFrom(src => src.Comment))
    .IgnoreAllNonExisting();

//+ Order Automapper setup
Mapper.CreateMap<OrderContract, Order>()
    .ForMember(x => x.Source, opt => opt.MapFrom(src => src.Source))
    .ForMember(x => x.Comment, opt => opt.MapFrom(src => src.Comment))
    //Although a mapping was created for Comment entity,
    //we still need to map the CommentId of the Order entity otherwise it will remain null during an update.
    //Another way to handle this would be to Delete CommentId from the Order entity.
    //However, if anyone updates (Update from model) OrderDataModel.edmx that property would show up again thus causing
    //a null value to be inserted during an update.
    .ForMember(x => x.CommentId, opt => opt.MapFrom(src => src.Comment.CommentId))
    .ForMember(x => x.SelectedRequirements, opt => {opt.UseDestinationValue(); opt.MapFrom(src => src.Requirements);})
    .ForMember(x => x.OrderStateId, opt => opt.MapFrom(src => src.StateId))
    .ForMember(x => x.OrderStateId, opt => opt.MapFrom(src => src.StateId))
    .IgnoreAllNonExisting();

到处使用 UseDestinationValue(这个不插入):

//+ Source
Mapper.CreateMap<SourceContract, Source>()
    .IgnoreAllNonExisting();

//+ SelectedRequirement
Mapper.CreateMap<SelectedRequirementContract, SelectedRequirement>()
    .ForMember(x => x.SelectedRequirementId, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.RequirementId); })
    .IgnoreAllNonExisting();

//+ Comment Contract
Mapper.CreateMap<CommentContract, Comment>()
    .ForMember(x => x.CommentText, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.Comment); })
    .IgnoreAllNonExisting();

//+ Order Automapper setup
Mapper.CreateMap<OrderContract, Order>()
    .ForMember(x => x.Source, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.Source); })
    .ForMember(x => x.Comment, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.Comment); })
    //Although a mapping was created for Comment entity,
    //we still need to map the CommentId of the Order entity otherwise it will remain null during an update.
    //Another way to handle this would be to Delete CommentId from the Order entity.
    //However, if anyone updates (Update from model) OrderDataModel.edmx that property would show up again thus causing
    //a null value to be inserted during an update.
    .ForMember(x => x.CommentId, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.Comment.CommentId); })
    .ForMember(x => x.SelectedRequirements, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.Requirements); })
    .ForMember(x => x.OrderStateId, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.StateId); })
    .ForMember(x => x.OrderStateId, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.StateId); })
    .IgnoreAllNonExisting();

我需要什么才能插入和更新?

最佳答案

我认为您想要的是让 AutoMapper 不创建您的 EF 实体并获取您发送的实体。在 2.0 版的自动映射器中,有一个映射方法的重载,您基本上可以在其中传递数据上下文委托(delegate)并让 EF 创建您的对象。

请看这个article .

关于c# - 使用 automapper 更新 Entity Framework 实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7810252/

相关文章:

c# - 如何在pcm流(C#)中查找音频功率(db)

c# - 获取 Entity Framework 中每个组的最后记录?

c# - Linq to Entities 组查询给出每组中的结果列表

c# - 如何让 Entity Framework Code First 和可为空的外键属性工作?

c# - 如何刷新 DbContext

c# - 在运行时更改语言的正确方法

c# - 使用 Linq 解析格式错误的 XML

asp.net-mvc - IdentityDbContext<ApplicationUser> vs DbContext for Repository

c# - 如何将数据库更改传播到我的 .edmx 文件?

c# - 如何编码 CSV 文件导入?