获取实体框架中被忽略的属性

本文关键字:属性 实体 框架 获取 | 更新日期: 2024-10-23 21:28:14

我使用EF开发一个框架。我想得到一个实体的所有被忽略的属性来构建一些特殊的查询。我该怎么做?

public class Customer
{
    public int Id { get; set; }
    public DateTime BirthDate { get; set; }
    public int Age { get; set; }
}
public class CustomerContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Customer>().Ignore(customer => customer.Age);
        base.OnModelCreating(modelBuilder);
    }
    public DbSet<Customer> Customers { get; set; }
}
public static class DbContextExtensions
{
    public static List<string> GetIgnoredProperties(this DbContext context, string entityTypeName)
    {
         // ???
    }
}

获取实体框架中被忽略的属性

我知道这不是在回答你最初的问题,在我的评论中我提到你应该使用反思,但那只是因为我读错了你的问题。

这里有一个使用反射的替代方法,如果你做得不对。

如果将[NotMapped]属性分配给类上要忽略的属性,则可以使用反射检索所有[NotMapped]属性。以下是如何实现这一目标的示例。

var resultArray = yourClassInstance.GetType().GetProperties()
                            .Where(prop => Attribute.IsDefined(prop, typeof(NotMappedAttribute)));

希望这对你有所帮助。

您可以通过调用DbModelBuilder.Build来实现您想要的。它将根据DbModelBuilder的配置设置创建DbModelDbModel公开了一个ConceptualModel,该模型包含上下文使用的类型。EdmModel保存上下文中声明的每个类型,对于每个类型,它保存DbModelBuilder在配置过程中未忽略的属性。因此,为了实现您想要的,您必须将每个实体类型的属性与EdmModel中存在的属性相交。它将给出它们之间的delta,而不是忽略的属性。这里有一个例子:

public class CustomerContext : DbContext
{
    private static IReadOnlyDictionary<Type, IReadOnlyCollection<PropertyInfo>> _ignoredProperties;
    /// Hold the ignored properties configured from fluent mapping
    public static IReadOnlyDictionary<Type, IReadOnlyCollection<PropertyInfo>> IgnoredProperties
    {
        get
        {
            return _ignoredProperties;
        }
    }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Customer>().Ignore(customer => customer.Age);
        // Build ignored properties only if they are not                
        if (_ignoredProperties == null)
        {                
            var model = modelBuilder.Build(this.Database.Connection);                
            var mappedEntityTypes = new Dictionary<Type, IReadOnlyCollection<PropertyInfo>>();
            foreach (var entityType in model.ConceptualModel.EntityTypes)
            {
                var type = Type.GetType(entityType.FullName);
                var typeProperties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
                var mappedProperties = entityType.DeclaredProperties.Select(t => t.Name)
                    .Union(entityType.NavigationProperties.Select(t => t.Name));
                mappedEntityTypes.Add(type, new ReadOnlyCollection<PropertyInfo>(
                    typeProperties.Where(t => !mappedProperties.Contains(t.Name)).ToList()));
            }
            _ignoredProperties = new ReadOnlyDictionary<Type, IReadOnlyCollection<PropertyInfo>>(mappedEntityTypes);
        }
        base.OnModelCreating(modelBuilder);
    }
    public DbSet<Customer> Customers { get; set; }
}

IgnoreProperties属性是将在第一次使用上下文时初始化的单例。在此之前,它将为null,因此必须确保在初始化之前没有任何东西使用它。它是只读的,所以你不必担心意外清空收藏。实体类型用作键,值公开包含被忽略属性的集合。使用示例:

var properties = CustomerContext.IgnoredProperties[typeof(Customer)];

缺点:

使用这种方法,DbModel将被构建两次,一次是收集被忽略的属性,第二次是由EntityFramework构建,此时DbCompiledModel将被缓存以用于未来的ObjectContext创建。它可能会对DbContext的冷启动产生影响,这意味着第一次在上下文上执行查询时会慢一点。这将取决于DbContext的大小。热情的询问不应受到影响。无论如何,OnModelCreating都将被调用一次。

优点:

对deDbModelBuilder配置所做的所有更改将自动反映在IgnoredProperties属性中。