Automapper可以将平面对象映射到复杂的对象图吗?
Mapper.CreateMap<PersonDto,Person>()
Run Code Online (Sandbox Code Playgroud)
将PersonDto.BirthCertificateFatherName映射到Person.BirthCertificate.FatherName
在我的ASP.NET MVC应用程序中,我将域模型与视图模型分开.
我在viewmodel对象中转换我的实体,这样我就可以只用所需的数据"提供"我的视图(我为此目的使用了valueinjecter).
在保存过程中,我的控制器返回viewmodel对象,将其转换为域模型实体并尝试使用SaveOrUpdate将其保留.我注意到,如果我尝试更新现有记录,Nhibernate会将其视为新对象并强制执行INSERT,即使我的实体具有正确的ID.
我之前没有加载(获取/加载)实体,因为我想避免再次重新映射所有字段.
有什么我做错了吗?实现这一目标的最佳方法是什么?
***** - 更新 - ***
我的控制器收到一个用户(ViewModel),验证它并尝试通过服务层将其保存为实体:
public ActionResult Edit(Guid id, Models.User User)
{
...
var user = new Domain.User();
user.InjectFrom(User);
user.SetId(id);
user = this._SecurityService.SaveUser(user);
}
Run Code Online (Sandbox Code Playgroud)
这是服务:
public Domain.User SaveUser(Domain.User User)
{
bool Result = false;
if (this._ValidationEngine.IsValid(User))
{
using (_UnitOfWork)
{
if (User.Code != Guid.Empty)
{
var user = this._UserRepository.Load(User.Code);
user.InjectFrom(User);
User = this._UserRepository.Update(user);
}
else {
User = this._UserRepository.Save(User);
}
Result = _UnitOfWork.Commit();
}
}
return (User);
}
Run Code Online (Sandbox Code Playgroud)
我很担心我必须多次转换我的viewmodel/entity.现在,当我尝试保存一个新用户时,我收到了这条消息:行被另一个事务更新或删除(或者未保存的值映射不正确)
可能这在某些方面与Darin告诉我的有关.
有没有更好的方法来做我想做的事情?
UPDATE …
nhibernate asp.net-mvc viewmodel asp.net-mvc-2 valueinjecter
我想我错过了一个带有valueinjecter和/或AutoMapper的简单概念,但是你如何深深地将父dto.Entity克隆到biz.Entity并包含所有孩子呢?
例如,biz.person.InjectFrom(dto.person).我想dto.person.AddressList集合到biz.person.AddressList收集拷贝,即使dto.Address和biz.Address有不同的类型,但具有相同的属性名称.
我的想法是,如果Parent属性名称拼写相同,例如AddressList,那么2个底层对象是否属于不同类型并不重要.它仍然会复制同名的简单类型,如int,string等.
谢谢
我正在使用ValueInjecter将属性从域模型映射到通过服务层提供的DTO.有问题的服务也接受更新...因此传入更新的DTO,然后将其注入域对象并保存.
// Domain
public class Member
{
public Country Country { get; set; }
}
public class Country
{
public string Code { get; set; }
public string Name { get; set; }
}
//Dto
public class MemberDto
{
public string CountryCode { get; set; }
}
//Transformation Method attempt 1
public Member InjectFromDto (MemberDto dto, Member source)
{
source = source.InjectFrom<UnflatLoopValueInjection>(dto);
return source;
}
Run Code Online (Sandbox Code Playgroud)
现在所有上面的代码都更新了Property Member.Country.Code,这显然不是我需要它做的.
所以从文档中,我想我需要创建一个覆盖并得到这个:
public class CountryLookup: UnflatLoopValueInjection<string, Country>
{
protected override Country SetValue(string …Run Code Online (Sandbox Code Playgroud) 我正在使用ValueInjecter进行对象映射,我正在尝试从ExpandoObject注入.我找到了一个从动态注入的例子.
public class Ac
{
public string Aa { get; set; }
}
[Test]
public void Aa()
{
var o = new { Aa = "aa" };
dynamic d = o;
var a = new Ac{ Aa = "bb" };
a.InjectFrom((object)d);
Assert.AreEqual(o.Aa, a.Aa);
}
Run Code Online (Sandbox Code Playgroud)
但是我还没有成功地使用ExpandoObject.我怎样才能做到这一点?
为映射配置的伪代码(如下)是不可能的,因为拉姆达只允许我们访问类型的IDataReader,wheras在实际测绘,AutoMapper将达到到每一个每一个"细胞" IDataRecord,而IDataReader.Read() == true:
var mappingConfig = Mapper.CreateMap<IDataReader, IEnumerable<MyDTO>>();
mappingConfig.ForMember(
destination => destination.???,
options => options.MapFrom(source => source.???));
Run Code Online (Sandbox Code Playgroud)
任何人都可以想到在运行时使用AutoMapper配置或只是满足下面要求的其他动态方法的方法.
要求是支持任何IDataReader可能具有与属性名称不匹配的列名称的传入,MyDTO并且没有我可以依赖的命名约定.相反,我们会要求用户在运行时将预期的列名称与IDataReadervia中找到的实际列名称交叉引用IDataReader.GetSchemaTable().
鉴于要求:
获取对象图,根据第二个字符串属性的处理值设置所有枚举类型属性.约定规定源字符串属性的名称将是具有后缀"Raw"的枚举属性的名称.
通过处理我们意味着我们需要剥离指定的字符等
我看过自定义格式化程序,值解析器和类型转换器,这些都不是解决方案吗?
我们希望使用AutoMapper而不是我们自己的反射例程,原因有两个:a)它在项目的其余部分广泛使用,b)它为您提供递归遍历ootb.
- 示例 -
鉴于下面的(简单)结构,这个:
var tmp = new SimpleClass
{
CountryRaw = "United States",
Person = new Person { GenderRaw="Male" }
};
var tmp2 = new SimpleClass();
Mapper.Map(tmp, tmp2);
Run Code Online (Sandbox Code Playgroud)
我们希望tmp2的MappedCountry枚举为Country.UnitedStates,Person属性的性别为Gender.Male.
public class SimpleClass1
{
public string CountryRaw {get;set;}
public Country MappedCountry {get;set;}
public Person Person {get;set;}
}
public class Person
{
public string GenderRaw {get;set;}
public Gender Gender {get;set;}
public string Surname {get;set;}
}
public enum Country
{
UnitedStates = 1,
NewZealand = …Run Code Online (Sandbox Code Playgroud) 我想我有两个选择:
1)从CodePlex下载:http://valueinjecter.codeplex.com/
2)从NuGet官方包源下载(目前下载次数仅为133次).
我更喜欢从NuGet下载,但我有点担心它的安全性.我不知道是谁制作了包裹.NuGet上的包是由ValueInjecter的作者或其他一些受信任的用户制作的吗?
谢谢
在我的 ASP.NET MVC4 应用程序中保存实体时,我遇到了 (2) 个字段的问题:
如你所知,这些领域将有特殊字符@和-典型。这是我使用 ValueInjecter 通过模型绑定从水合对象注入我的模型类的控制器代码:
public ActionResult Create(TestViewModel testViewModel)
{
using (var context = new MyEntities())
{
var person = new Person();
person.InjectFrom(testViewModel);
context.Person.AddObject(person);
context.SaveChanges();
}
}
Run Code Online (Sandbox Code Playgroud)
我得到的错误如下:
“字符串或二进制数据将被截断。语句已终止”
乍一看,您可能会说这是 SQL 中字段的大小,但由于这些特殊字符,真正的问题被伪装了。如果我为字段输入以下内容:
电话:11234565454514564561
电子邮件:blahblahblahblah
...然后一切正常。
但是,如果我输入:
电话:123-456-7890
电子邮件:test@wow.com
我收到有关“字符串或二进制数据将被截断”的错误消息。所以我找到了一个解决方法,但这似乎完全没有必要,而且可能是错误的方式。如果我使用 C# 转义字符将值从模型绑定对象显式映射到实体,那么我的值将插入如下所示:
public ActionResult Create(TestViewModel testViewModel)
{
using (var context = new MyEntities())
{
var person = new Person();
person.InjectFrom(testViewModel);
//Explicitly map items preserving special charachters
person.EmailAddress = @testViewModel.EmailAddress;
person.Phone …Run Code Online (Sandbox Code Playgroud) 我在使用ValueInjecter创建EntityFramework POCO的深层克隆到类似的DTO类时遇到了问题.
如果我从具有导航属性的多个相关实体/子实体的复杂POCO对象注入更简单的DTO,则ValueInjecter似乎仍然触及多个属性值并导致从数据库延迟加载此数据.
我相信ValueInjecter获取特定源对象中每个属性的值,因为它准备将值注入指定的目标.
我的实际项目相当复杂,但作为一个例子,我采用了NerdDinner示例并以更简单的方式复制了该问题.(NerdDinner是使用EF4的第一个代码示例(ScottGu NerdDinner示例).
所以我有两个模型类.
public class Dinner
{
public int DinnerId { get; set; }
public string Title { get; set; }
public DateTime EventDate { get; set; }
public string Address { get; set; }
public string HostedBy { get; set; }
public virtual ICollection<RSVP> Rsvps { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
和
public class RSVP
{
public int RsvpID { get; set; }
public int DinnerID { get; set; }
public string AttendeeEmail { …Run Code Online (Sandbox Code Playgroud) valueinjecter ×10
c# ×4
automapper ×3
asp.net-mvc ×2
nhibernate ×2
.net ×1
automapping ×1
dto ×1
enums ×1
mapping ×1
system.data ×1
viewmodel ×1
wcf ×1