Entity Framework DbSet Reflection

I am trying to iterate over all the DbSets in my DbContext that contain objects with a specific base type. My goal is to use this loop before I call SaveChanges in my DbContext and set some default options.

In C #, my base class is as follows: -

public abstract class TrackedEntity
{
    public string ModifiedBy { get; set; }

    public DateTime Modified { get; set; }
}

An example of a derived class: -

public class Record : TrackedEntity
{
    [Key]
    public int ID { get; set; }

    public string Name { get; set; }
}

I created my own SaveChanges method in my DbContext class and I can get a ProtertyInfo list for each DbSet containing TrackedEntity, but when I try to skip the values ​​in each DbSet, I get an error because I cannot execute my DbSet of a derived class (e.g. DbSet <Record>) in a DbSet base class (e.g. DbSet <TrackedEntity>).

public class MyContext : DbContext
{
    public DbSet<Record> Records { get; set; }

    public int SaveChanges(string username)
    {
        //Set TrackedEnity update columns
        foreach (PropertyInfo property in GetDbSetPropertyInfos<TrackedEntity>())
        {
            foreach (TrackedEntity entity in (DbSet<TrackedEntity>)property.GetValue(this, null)) //fails here due to cast
            {
                entity.Modified = DateTime.UtcNow;
                entity.ModifiedBy = username;
            }
        }
        return base.SaveChanges();
    }

    //return a list of PropertyInfo for each DbSet with a given type in this context
    IEnumerable<PropertyInfo> GetDbSetPropertyInfos<T>() where T : class
    {
        IEnumerable<PropertyInfo> properties = GetType().GetProperties().Where(p => p.PropertyType.IsGenericType
            && p.PropertyType.Name.StartsWith("DbSet")
            && p.PropertyType.GetGenericArguments().Length > 0
            && p.PropertyType.GetGenericArguments()[0].IsSubclassOf(typeof(T)));

        return properties;
    }
}

Does anyone know if what I am trying to achieve is possible?

+4
1

ChangeTracker.

....
foreach( var entry in context.ChangeTracker.Entries<TrackedEntity>())
{
    if(entry.State!=EntityState.Unchanged)
    {
        TrackedEntity entity = entry.Entity;
        entity.Modified = DateTime.UtcNow;
        entity.ModifiedBy = username;
    }
}
context.SaveChanges();
+3

Source: https://habr.com/ru/post/1547345/


All Articles