在Entity Framework中获取被忽略的属性 [英] Get ignored properties in Entity Framework

查看:173
本文介绍了在Entity Framework中获取被忽略的属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在EF框架上工作。我想获取一个实体的所有被忽略的属性来构建一些特殊的查询。我该怎么做?

  public class Customer 
{
public int Id {get;组; }
public DateTime BirthDate {get;组; }
public int Age {get;组;
}

public class CustomerContext:DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity< Customer> ;()。忽略(customer => customer.Age);
base.OnModelCreating(modelBuilder);
}

public DbSet< Customer>客户{get;组; }
}

public static class DbContextExtensions
{
public static List< string> GetIgnoredProperties(这个DbContext上下文,string entityTypeName)
{
// ???
}
}


解决方案

你可以通过调用 DbModelBuilder.Build 。它将通过 DbModelBuilder 在配置设置上创建一个 DbModel DbModel 公开了一个包含上下文使用的类型的 ConceptualModel EdmModel 保留在上下文中声明的每个类型,对于每个类型,它保存在配置期间由 DbModelBuilder 未被忽略的属性。所以,要实现你想要的,你必须将每个实体类型的属性与 EdmModel 中存在的属性相交。它将给予它们之间的三角洲,因此被忽略的属性。这里有一个例子:

  public class CustomerContext:DbContext 
{
private static IReadOnlyDictionary< Type,IReadOnlyCollection< PropertyInfo>> _ignoredProperties;
///保持由流畅映射配置的忽略属性
public static IReadOnlyDictionary< Type,IReadOnlyCollection< PropertyInfo>> IgnoredProperties
{
get
{
return _ignoredProperties;
}
}

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity< Customer>()忽略(customer => customer.Age);

//仅当它们不是
时才构建忽略的属性if(_ignoredProperties == null)
{
var model = modelBuilder.Build(this.Database.Connection );
var mappedEntityTypes = new Dictionary< Type,IReadOnlyCollection< PropertyInfo>>();
foreach(model.ConceptualModel.EntityTypes中的var entityType)
{
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>客户{get;组; }
}

IgnoreProperties 属性是一个单例,在第一次使用上下文时初始化它们。在此之前它将为null,所以必须确保在初始化之前没有使用它。这是唯一的,所以你不必担心意外清除收集。实体类型用作关键字,该值会暴露一个包含忽略属性的集合。使用示例:

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



缺点:



DbModel 将建立两次,一次收集被忽略的属性,第二次由EntityFramework在 DbCompiledModel 将被缓存为未来的 ObjectContext 创建。它可以对 DbContext 的冷启动产生影响,这意味着您将在第一时间对您的上下文执行查询,这将会稍慢一些。它将取决于 DbContext 的大小。热烈的查询不应该受损。 OnModelCreating will无论如何,无论如何,请再次打电话



优点:



在de DbModelBuilder 配置将自动反映在 IgnoredProperties 属性中。


I work on a framework with EF. I want to get all ignored properties of an entity to build some special queries. How can I do it?

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)
    {
         // ???
    }
}

解决方案

You can achieve what you want by calling the DbModelBuilder.Build. It will create a DbModel base on configuration setup by the DbModelBuilder. The DbModel expose a ConceptualModel that hold the types used by the context. The EdmModel hold each type that are declared in the context, and for each type, it hold the properties that has not been ignored by the DbModelBuilder during it's configuration. So, to achieve what you want, you have to intersect the properties of each entity type with those present in the EdmModel. It will give the delta between them, thefore the ignored properties. Here an example :

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; }
}

The IgnoreProperties property is a singleton that will be initialized the first time you will use the context. It will be null before that, so will have to ensure that nothing use it until it's initialized. It's readonly, so you don't have to worrie about accidental clear of the collection. The entity type is used as key, and the value expose a collection that hold ignored properties. Example of use :

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

Cons :

With this approach is that the DbModel will be built twice, one time to gather the ignored properties, and second time by EntityFramework when the DbCompiledModel will be cached for futur ObjectContext creation. It can have an impact on the cold start of the DbContext, it means that the fist time you will execute a query over your context, it will be a bit slower. It will depend on the size of the DbContext. Warm queries should not suffer. OnModelCreating will be called once anyway.

Pros :

All changes made on de DbModelBuilder configuration will be automatically reflected in the IgnoredProperties property.

这篇关于在Entity Framework中获取被忽略的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆