我是EF的新手,正在努力进行似乎基本的更新。我已经阅读了许多有关类似问题的文章。据我所知,目前在EF Core 2.1中不容易做到这一点,并且需要一个复杂的解决方法。这实际上可行吗?还是我应该直接直接且单独地更新子实体?
注意:如果我只是更新exampleA而不包含子实体,则可以正常工作。
我收到以下错误:
处理请求时发生未处理的异常。InvalidOperationException:无法跟踪实体类型“ ExampleB”的实例,因为已经跟踪了另一个具有相同“ {'Id”}键值的实例。附加现有实体时,请确保仅附加一个具有给定键值的实体实例。考虑使用'DbContextOptionsBuilder.EnableSensitiveDataLogging'来查看冲突的键值。Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap.ThrowIdentityConflict(InternalEntityEntry条目)
堆栈查询cookie标头InvalidOperationException:无法跟踪实体类型ExampleB的实例,因为已经跟踪了另一个具有相同键值的{'Id'}的实例。附加现有实体时,请确保仅附加一个具有给定键值的实体实例。考虑使用'DbContextOptionsBuilder.EnableSensitiveDataLogging'来查看冲突的键值。
我创建了该问题的基本示例。第一个stackoverflow帖子也让我知道是否需要更多信息。
任何帮助将不胜感激。
WebAPI控制器:
[HttpPut]
public async Task<ActionResult> UpdateExample(ExampleADto exampleADto)
{
var exampleAFromDB = await _context.ExampleA.Include(x => x.ExampleBs).Where(x => x.Id == exampleADto.Id).SingleOrDefaultAsync();
if (exampleAFromDB == null)
return NotFound();
_mapper.Map(exampleADto, exampleAFromDB);
if (await _context.SaveChangesAsync() > 0)
return Ok(exampleAFromDB);
throw new Exception("Failed to update ExampleA");
}
Run Code Online (Sandbox Code Playgroud)
更新之前在数据库中的exampleA:
{
"id": 1,
"description": "Example A1",
"exampleBDtos": [
{
"id": 1,
"description": "B1",
"someNumber": 1
},
{
"id": 2,
"description": "B2",
"someNumber": 2
},
{
"id": 3, …Run Code Online (Sandbox Code Playgroud) 如何使AutoMapper将缺少的未映射属性映射到目标对象内的字典?(类似于序列化期间的ExtensionData)
例:
class Source
{
public int A {get;set;}
public int B {get;set;}
public int C {get;set;}
}
class Destination
{
public int A {get;set;}
public Dictionary<string, object> D {get;set;}
}
Source s = new Source { A = 1, B = 2, C = 3 };
Destination d = ... // Mapping code
Run Code Online (Sandbox Code Playgroud)
现在我想要以下结果:
d.A ==> 1
d.D ==> {{ "B", 2 }, { "C", 3 }}
Run Code Online (Sandbox Code Playgroud)
*编辑*
最后,我正在寻找一种无反射的解决方案。含义:在设置/配置/初始化期间允许反射,但是在映射本身期间,我不希望反射引起任何延迟。
*编辑*
我正在寻找一种通用的解决方案,就像序列化程序一样。
我有一个动态对象(实际上,来自JSON.NET的JObject)是从JSON动态构建的.我想将其属性复制到现有对象.动态对象的属性应该存在于目标对象的类型中,否则,可以有错误.我正在研究Automapper,最新版本.我试图从JObject创建一个映射到正确的类型,但我不认为它会工作,因为JObject中的属性存储在内部字典中.这有可能吗?
我们在另一个类中有一个类作为属性,需要使用Automapper进行映射。我们已经编写了一个解析器,它将源类属性映射到destinationMember属性。我写了下面的逻辑不起作用。
我们收到以下错误。
错误映射类型。
映射类型:SubscriberDTO-> Subscriber ConsoleAutomapperTestHarness.SubscriberDTO-> ConsoleAutomapperTestHarness.Subscriber
键入映射配置:SubscriberDTO-> Subscriber ConsoleAutomapperTestHarness.SubscriberDTO-> ConsoleAutomapperTestHarness.Subscriber
属性:SubscriberSettings
using AutoMapper; //5.1.1.0
using System;
namespace ConsoleAutomapperTestHarness
{
public class Program
{
public static void Main(string[] args)
{
SubscriberDTO subDTO = new SubscriberDTO();
subDTO.AllowAddPFA = true;
subDTO.AllowAutoPay = true; ;
subDTO.SubscriberID = 10000;
subDTO.FirstName = "Kishor";
new SubscriberAutoMapper();
Subscriber sub = Mapper.Map<SubscriberDTO, Subscriber>(subDTO);
Console.WriteLine(sub.SubscriberSettings.AllowAddPFA.ToString());
Console.ReadLine();
}
}
public class SubscriberAutoMapper
{
public SubscriberAutoMapper()
{
Mapper.Initialize(cfg => {
cfg.CreateMap<SubscriberDTO, Subscriber>()
.ForMember(dest => dest.SubscriberSettings, opt => opt.ResolveUsing<SubscriberAutoMapperResolver>());
});
Mapper.AssertConfigurationIsValid();
} …Run Code Online (Sandbox Code Playgroud) 我正在尝试从源的子对象映射到目标(作为父对象)。
源模型:
public class SourceBaseResponse<T> where T : new()
{
public string Type { get; set; }
public string Id { get; set; }
public T Attributes { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
对于我的示例,我正在使用T为SourceAssignment类型
public class SourceAssignment
{
public string Id { get; set; }
public string Email { get; set; }
public string EmployeeId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTimeOffset CreatedAt { get; set; }
} …Run Code Online (Sandbox Code Playgroud) 我从旧版本的AutoMapper升级并转换了我的自定义解析器,但我很难过.
public class ProductMappingProfile : Profile
{
public ProductMappingProfile()
{
CreateMap<Product, ProductViewModel>()
.ForMember(
dest => dest.Model,
opt => opt.ResolveUsing<ModelNameResolver>(src => src.ModelId));
// won't compile
}
}
Run Code Online (Sandbox Code Playgroud)
Product具有int? ModelId属性且ProductViewModel具有string Name属性.
public class ModelNameResolver : IValueResolver<short?, string, string>
{
private readonly InventoryService _inventoryService;
public ModelNameResolver(InventoryService inventoryService)
{
_inventoryService = inventoryService;
}
public string Resolve(short? source, string destination, string destMember, ResolutionContext context)
{
if (!source.HasValue)
return "n/a";
return _inventoryService.GetModel(source.Value)
.Name;
}
}
Run Code Online (Sandbox Code Playgroud)
The type 'MyNamespace.Web.Resolvers.ModelCodeResolver' cannot be …Run Code Online (Sandbox Code Playgroud) 我只是尝试将AutoMapper升级到5.0.2,但遇到了障碍。
根据迁移文档,值解析器现在可以访问目标对象:
值解析器的签名已更改,以允许访问源/目标模型。
结果是,每个值解析器都精确地绑定到一个目标类型。
但是,我们的某些价值解析器可用于多种目的地类型。例如,我们有一个解析器,用于映射DTO的所有ID属性。解析程序通过注入到解析程序中的服务来修改ID。
如何在AutoMapper 5中定义可重用的值解析器,这样我就不必为具有完全相同的实现的每种目标类型创建专用的解析器?
注意:使用值解析器而不是直接操作值的主要原因是依赖项注入。按照这个答案,值解析器是在映射过程中使用依赖项注入服务的最佳方法。
这是我的问题,Condition我想获得正在评估的当前属性的名称。我相信你可以在早期版本的 Automapper 中做到这一点。有什么建议?
[TestFixture]
public class SandBox
{
public class MySource
{
public string Name { get; set; }
public int Count { get; set; }
}
public class MyDestination
{
public string Name { get; set; }
public int Count { get; set; }
}
public class SourceProfile : Profile
{
public SourceProfile()
{
this.CreateMap<MySource, MyDestination>()
.ForAllMembers(x => x.Condition((source, destination, arg3, arg4, resolutionContext) =>
{
// this will run twice (once for every property)
// but how …Run Code Online (Sandbox Code Playgroud) System.StackOverflowException我在尝试在 AutoMapper 5 中映射以前在 AutoMapper 4 中使用的某些内容时遇到了问题。
经过一番谷歌搜索后,我发现它是由Circularreferences引起的。
AutoMapper 文档说:
以前,AutoMapper 可以通过跟踪映射的内容来处理循环引用,并在每个映射上检查源/目标对象的本地哈希表以查看该项目是否已映射。事实证明,这种跟踪非常昂贵,您需要选择使用 PreserveReferences 才能使圆形地图发挥作用。或者,您可以配置 MaxDepth:
Run Code Online (Sandbox Code Playgroud)// Self-referential mapping cfg.CreateMap<Category, CategoryDto>().MaxDepth(3); // Circular references between users and groups cfg.CreateMap<User, UserDto>().PreserveReferences();
所以我添加.MaxDepth(3)到我的代码中,它现在又可以工作了。
但是我不明白真正的问题是什么以及我通过添加该行做了什么:)
我的问题:
.MaxDepth()?为什么示例中使用 3?.PreserveReferences()为了什么?我尝试在新版本的 AutoMapper 中实现 IValueResolver 接口。我已经实现了 ResourceTypeResolver 类如下..
public interface IValueResolver<in TSource, in TDestination, TDestMember>
{
TDestMember Resolve(TSource source, TDestination destination, TDestMember destMember, ResolutionContext context);
}
public class ResourceTypeResolver : IValueResolver<PMEasy.Model.Entity.Resource, PMEasy.Web.Models.Gantt.GanttResource, string>
{
private ILookupService LookupService;
public ResourceTypeResolver(ILookupService lookupService)
{
LookupService = lookupService;
}
public string Resolve(PMEasy.Model.Entity.Resource source, PMEasy.Web.Models.Gantt.GanttResource destination, string member, ResolutionContext context)
{
if (source.Type.HasValue && source.Type != Guid.Empty)
{
var resourceType = LookupService.GetLookupListByName("ResourceType").Where(con => con.GUID == source.Type.Value).FirstOrDefault();
return resourceType != null ? resourceType.Value : string.Empty;
}
else …Run Code Online (Sandbox Code Playgroud)