EF Code First如何通过Fluent API防止属性映射?

32

我有一个类 Product 和一个复杂类型 AddressDetails

public class Product
{
    public Guid Id { get; set; }

    public AddressDetails AddressDetails { get; set; }
}

public class AddressDetails
{
    public string City { get; set; }
    public string Country { get; set; }
    // other properties
}

有没有可能防止将“AddressDetails”中的“Country”属性映射到“Product”类中?(因为我永远不需要它在“Product”类中)

就像这样

Property(p => p.AddressDetails.Country).Ignore();

2
你已经重写了DbContext.OnModelCreating吗?在那个方法中,modelBuilder.Entity<Product>().Ignore(p => p.AddressDetails.Country)是否失败了? - Twon-ha
当我使用Entity Framework 4.4时,它对我有用。 - Twon-ha
1
你是否考虑过为 Product.AddressDetail 使用不同的类?它显然与其他地方使用的 AddressDetail 有不同的行为。 - Aron
1
@RaraituL 您的意思是您试图避免使用SOLID设计原则吗?http://en.wikipedia.org/wiki/Liskov_substitution_principle - Aron
1
@RaraituL,如果忽略代码生效,将会破坏LSP。如果您使用假设“Country!= null”的函数来运行“Product.AddressDetail”,它将抛出异常。因此,LSP被违反了。另外,少的类并不意味着简单。在您的情况下,您已经创建了一个新的边缘情况,这并不是KISS原则。 - Aron
显示剩余7条评论
7个回答

31

对于EF5及更早版本: 在您的上下文中覆盖DbContext.OnModelCreating

modelBuilder.Entity<Product>().Ignore(p => p.AddressDetails.Country);

对于EF6:很遗憾,你没有办法。请参见Mrchief的答案


3
不起作用:表达式“p => p.AddressDetails.Country”不是有效的属性表达式。该表达式应该表示一个属性:C#:“t => t.MyProperty” VB.Net:“Function(t) t.MyProperty”。 - Mrchief
1
@Mrchief 对的,这是针对旧版本的。我已经添加了一个链接到你的答案,因为那是当前 EF 版本的正确答案。 - Twon-ha
1
很遗憾他们在EF6中积极阻止了这一点。希望这是出于某些隐藏的良好原因。 - Søren Boisen
这真的很烦人。看起来他们已经删除了功能。 - Jeremy Holovacs

15

不幸的是,所接受的答案并不起作用,至少在使用EF6时尤其如此,特别是如果子类不是实体类。

我没有发现通过流畅API进行此操作的任何方法。唯一的方法是通过数据注释来实现:

public class AddressDetails
{
    public string City { get; set; }

    [NotMapped]
    public string Country { get; set; }
    // other properties
}

注意:如果你遇到这样一种情况,即只有在特定的其他实体中 Country 才应该被排除在外,那么采用这种方法就行不通了。


“如果子类不是实体”是什么意思?如果子类是“ComplexType”呢? - Catalin
是的。如果它是一个实体,你可以添加它自己的配置并跳过映射。 - Mrchief
@Mrchief,您可以尝试使用Fluent API来实现modelBuilder.ComplexType<AddressDetails>().Ignore(ad => ad.Country)的相同结果。 - Verbon

11
如果您正在使用EntityTypeConfiguration的实现,您可以使用Ignore方法:
public class SubscriptionMap: EntityTypeConfiguration<Subscription>
{
    // Primary Key
    HasKey(p => p.Id)

    Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    Property(p => p.SubscriptionNumber).IsOptional().HasMaxLength(20);
    ...
    ...

    Ignore(p => p.SubscriberSignature);

    ToTable("Subscriptions");
}

你的意思是它不能与复杂类型一起使用吗?当你在属性声明中添加 virtual 关键字时,复杂类型的映射将自动完成。如果你不想进行映射,只需删除 virtual 关键字即可。 - Maxime
哦,你的意思是在嵌套对象中...我明白了。 - Maxime

4
虽然我知道这是一个老问题,但答案并没有解决我的EF 6问题。
对于EF 6,您需要创建一个ComplexTypeConfiguration映射。
例如:
public class Workload
{
    public int Id { get; set; }
    public int ContractId { get; set; }
    public WorkloadStatus Status {get; set; }
    public Configruation Configuration { get; set; }
}
public class Configuration
{
    public int Timeout { get; set; }
    public bool SaveResults { get; set; }
    public int UnmappedProperty { get; set; }
}

public class WorkloadMap : System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<Workload>
{
    public WorkloadMap()
    {
         ToTable("Workload");
         HasKey(x => x.Id);
    }
}
// Here This is where we mange the Configuration
public class ConfigurationMap : ComplexTypeConfiguration<Configuration>
{
    ConfigurationMap()
    {
       Property(x => x.TimeOut).HasColumnName("TimeOut");
       Ignore(x => x.UnmappedProperty);
    }
}

如果您的上下文手动加载配置,则需要添加新的ComplexMap;如果使用FromAssembly重载,则它将与其余配置对象一起被拾取。

2
在 EF6 中,您可以配置复杂类型:
 modelBuilder.Types<AddressDetails>()
     .Configure(c => c.Ignore(p => p.Country))

这样,属性“Country”将始终被忽略。


1

试试这个

modelBuilder.ComplexType<AddressDetails>().Ignore(p => p.Country);

在类似情况下,这对我很有效。


-2

这也可以在Fluent API中完成,只需在映射中添加以下代码

this.Ignore(t => t.Country),在EF6中进行了测试


2
问题是关于在复杂类型上忽略属性。这种情况在EF6下无法正常工作。 - Søren Boisen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接