首页 > 解决方案 > 获取更新的实体对象类型

问题描述

几天来我一直在努力解决这个问题。我有一个使用基于服务的数据库通过 EF6 交互的 wpf 应用程序。

我想检测哪个实体类型已更新,因此我只能更新其相对数据网格 DBContext 现在看起来像这样

    public partial class DataEntities : DbContext
    {
        public DataEntities()
            : base("name=DataEntities")
        {
        }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            throw new UnintentionalCodeFirstException();
        }
    
        public virtual DbSet<Anni> Anni { get; set; }
        public virtual DbSet<Classi> Classi { get; set; }
        public virtual DbSet<ClassiConcorso> ClassiConcorso { get; set; }
        public virtual DbSet<Discipline> Discipline { get; set; }
        public virtual DbSet<Docenti> Docenti { get; set; }
        public virtual DbSet<Indirizzi> Indirizzi { get; set; }
        public virtual DbSet<Sedi> Sedi { get; set; }
        public virtual DbSet<SistemaOrario> SistemaOrario { get; set; }
        public virtual DbSet<VisualizzaClassi> VisualizzaClassi { get; set; }
        public virtual DbSet<VisualizzaDocenti> VisualizzaDocenti { get; set; }
        public virtual DbSet<VisualizzaSistemaOrario> VisualizzaSistemaOrario { get; set; }
        public virtual DbSet<VisualizzaTotaleOre> VisualizzaTotaleOre { get; set; }
        public virtual DbSet<VisualizzaTotaleOrePerClasseConcorso> VisualizzaTotaleOrePerClasseConcorso { get; set; }

        public event EventHandler SavingMultipleChanges;
        public event EventHandler SavingAnniChanges;
        public event EventHandler SavingClassiChanges;
        public event EventHandler SavingClassiConcorsoChanges;
        public event EventHandler SavingDisciplineChanges;
        public event EventHandler SavingDocentiChanges;
        public event EventHandler SavingIndirizziChanges;
        public event EventHandler SavingSediChanges;
        public event EventHandler SavingSistemaOrarioChanges;

        public override int SaveChanges()
        {
            // Notify objects that want to know, that we are gonna save some stuff
            IEnumerable<DbEntityEntry> changes = this.ChangeTracker.Entries().Where(t => t.State != EntityState.Unchanged);
            if (changes.Count() == 1)
            {
                var change = changes.ElementAt(0);
                if (change.Entity.GetType() == Anni.Create().GetType())
                {
                    SavingAnniChanges.Invoke(this, new EventArgs());
                }
                if (change.Entity.GetType() == Sedi.Create().GetType())
                {
                    SavingClassiChanges.Invoke(this, new EventArgs());
                }
                if (change.Entity.GetType() == ClassiConcorso.Create().GetType())
                {
                    SavingClassiConcorsoChanges.Invoke(this, new EventArgs());
                }
                if (change.Entity.GetType() == Discipline.Create().GetType())
                {
                    SavingDisciplineChanges.Invoke(this, new EventArgs());
                }
                if (change.Entity.GetType() == Docenti.Create().GetType())
                {
                    SavingDocentiChanges.Invoke(this, new EventArgs());
                }
                if (change.Entity.GetType() == Indirizzi.Create().GetType())
                {
                    SavingIndirizziChanges.Invoke(this, new EventArgs());
                }
                if (change.Entity.GetType() == Sedi.Create().GetType())
                {
                    SavingSediChanges.Invoke(this, new EventArgs());
                }
                if (change.Entity.GetType() == SistemaOrario.Create().GetType())
                {
                    SavingSistemaOrarioChanges.Invoke(this, new EventArgs());
                }
            }
            else
            {
                SavingMultipleChanges.Invoke(this, new EventArgs());
            }

            // Call the actual SaveChanges method to apply the changes to the database
            return base.SaveChanges();
        }
    }

所以这行得通,有没有更好的方法来做到这一点?

请注意,这是版本 0,接下来将是通过 EventArgs 传递类型的单个事件

标签: c#entity-frameworkentity-framework-6

解决方案


这可以通过反射实现,但您需要确保每个事件名称都与单个模式匹配

var change = changes.ElementAt(0);

var entityType = change.Entity.GetType();
var eventDelegate = (Delegate)GetType()
    .GetField("Saving" + entityType.Name + "Changes", BindingFlags.Instance | BindingFlags.NonPublic)
    .GetValue(this);

if (eventDelegate != null)
{
    eventDelegate.DynamicInvoke(this, EventArgs.Empty);
}
else 
{
    throw new NotImplementedException("Event handler not implemented for type " + entityType.Name);
}

稍后您可以创建一些通用事件处理程序参数来传递给您的事件

public class GenericEventArgs<T> : EventArgs
{
    public T Item { get; set; }
}

以及创建实例的代码

var eventArgsType = typeof(GenericEventArgs<>).MakeGenericType(entityType);
var eventArgs = Activator.CreateInstance(eventArgsType);
eventArgsType.GetProperty("Item").SetValue(eventArgs, change);

推荐阅读