【发布时间】:2018-03-22 08:37:54
【问题描述】:
用例如下:客户帐户只有一个地址,可以是送货地址,也可以是账单地址。我需要将其合并到一个地址实体中。最重要的是,地址行是数据库中的单独列,但必须是 DTO 中字符串的 IEnumerable。一直以来,这必须支持 ProjectTo(),因为必须实现 OData。如何在不更改任何数据库的情况下完成此操作?由于遗留应用程序,我无法触摸它。
第一个代码示例有效,而第二个代码示例失败:The nested query is not supported. Operation1='Case' Operation2='Collect'。这可能是因为它必须创建子实体。我怎样才能让它工作?是否有任何解决方法(也许重组我的实体)?
在第一个示例中,我将不同地址行列的映射添加到List<string>。然后当调用 .Include() Entity Framework 时,它确切地知道该做什么并且它起作用了。
public void Main()
{
Mapper.Initialize(cfg =>
{
cfg.CreateMap<ShippingAddress, DtoShippingAddress>
.ForMember(dto => dto.AddressLines,
entity => entity.MapFrom(source => new List<string>
{
source.AddressLine1,
source.AddressLine2,
source.AddressLine3
}));
cfg.CreateMap<BillingAddress, DtoBillingAddress>
.ForMember(dto => dto.AddressLines,
entity => entity.MapFrom(source => new List<string>
{
source.AddressLine1,
source.AddressLine2,
source.AddressLine3
}));
});
Mapper.AssertConfigurationIsValid();
var context = new ClientContext();
var result = context.CustomerAccounts.Include(i => i.ShippingAddress).Include(i => i.BillingAddress).ProjectTo<DtoCustomerAccount>();//.Dump();
}
public class CustomerAccount
{
public int Id { get; set; }
public ShippingAddress ShippingAddress { get; set; }
public BillingAddress BillingAddress { get; set; }
}
public class ShippingAddress
{
public int Id { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string AddressLine3 { get; set; }
}
public class BillingAddress
{
public int Id { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string AddressLine3 { get; set; }
}
public class DtoCustomerAccount
{
public int Id { get; set; }
public DtoShippingAddress ShippingAddress { get; set; }
public DtoBillingAddress BillingAddress { get; set; }
}
public class DtoShippingAddress
{
public int Id { get; set; }
public List<string> AddressLines { get; set; }
}
public class DtoBillingAddress
{
public int Id { get; set; }
public List<string> AddressLines { get; set; }
}
public class Initializer : DropCreateDatabaseAlways<ClientContext>
{
protected override void Seed(ClientContext context)
{
context.CustomerAccounts.Add(new UserQuery.CustomerAccount {ECommercePublished=true, Articles = new []{ new Article{IsDefault=true, NationId=1, ProductId=1}}});
}
}
public class ClientContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.Log = s=>Debug.WriteLine(s);
Database.SetInitializer(new Initializer());
}
public DbSet<CustomerAccount> CustomerAccounts { get; set; }
}
我需要的实现方式,失败了:
//The nested query is not supported. Operation1='Case' Operation2='Collect'
public void Main()
{
Mapper.Initialize(cfg =>
{
cfg.CreateMap<CustomerAccount, DtoCustomerAccount>
.ForMember(dto => dto.Address,
entity => entity.MapFrom(source =>
source.BillingAddress == null
? new Address
{
Id = source.ShippingAddress.Id,
AddressLines = new [] // or new List<string>
{
source.ShippingAddress.AddressLine1,
source.ShippingAddress.AddressLine2,
source.ShippingAddress.AddressLine3
}
}
: new Address
{
Id = source.BillingAddress.Id,
AddressLines = new [] // or new List<string>
{
source.BillingAddress.AddressLine1,
source.BillingAddress.AddressLine2,
source.BillingAddress.AddressLine3
}
}));
});
Mapper.AssertConfigurationIsValid();
var context = new ClientContext();
var result = context.CustomerAccounts.ProjectTo<DtoCustomerAccount>();//.Dump();
}
public class CustomerAccount
{
public int Id { get; set; }
public ShippingAddress ShippingAddress { get; set; }
public BillingAddress BillingAddress { get; set; }
}
public class ShippingAddress
{
public int Id { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string AddressLine3 { get; set; }
}
public class BillingAddress
{
public int Id { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string AddressLine3 { get; set; }
}
public class DtoCustomerAccount
{
public int Id { get; set; }
public DtoAddress Address { get; set; }
}
public class DtoAddress
{
public int Id { get; set; }
public List<string> AddressLines { get; set; }
}
public class Initializer : DropCreateDatabaseAlways<ClientContext>
{
protected override void Seed(ClientContext context)
{
context.CustomerAccounts.Add(new UserQuery.CustomerAccount {ECommercePublished=true, Articles = new []{ new Article{IsDefault=true, NationId=1, ProductId=1}}});
}
}
public class ClientContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.Log = s=>Debug.WriteLine(s);
Database.SetInitializer(new Initializer());
}
public DbSet<CustomerAccount> CustomerAccounts { get; set; }
}
【问题讨论】:
标签: c# entity-framework automapper