Get ignored properties in Entity Framework

你。 提交于 2019-12-07 17:04:23

问题


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

回答1:


I know this is not answering your original question, and in my comments I mentioned that you should use reflection, but that was only because I read your question wrong.

Here is an alternative using reflection, for if you do not come right.

If you assign the [NotMapped] attribute to the properties on your class that you would like to ignore, you could possibly retrieve all [NotMapped] properties using reflection. Below is an example of how this could be achieved.

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

Hope this helps you in some way.




回答2:


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.



来源:https://stackoverflow.com/questions/36760036/get-ignored-properties-in-entity-framework

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!