lundi 9 septembre 2019

calling EntityTypeBuilder

I'm attempting to add "History" tables to EFCore, and have it mostly working. For every POCO in my model that has a [Historyable] attribute on the class, I use reflection to generate a new class that has three additional properties in addition to the properties that are in the original class - ChangeDate, ChangeType, and ChangeUserID.

My problem comes when I need to set the primary key for the new generated History type. In hand written code, adding the primary keys would look something like:

modelBuilder.Entity<EquipmentPortProfile>().HasKey(k => new { k.Name, k.PortType, k.CardType })
modelBuilder.Entity<EquipmentPortProfileHistory>().HasKey(k => new { k.Name, k.PortType, k.CardType, k.ChangeDate })  // add ChangeDate to keep it unique

where EquipmentPortProfile is the original [Historable] POCO that I can manually call HasKey() for and EquipmentPortProfileHistory is the new generated type that I need to call HasKey() for via reflection.

I've got the following code which adds the new History type of the model, but I can't quite figure out how to generically invoke the call to HasKey() with the List of MemberExpressions I've built.

var type = tbuilder.CreateType();  // create the new History type
var entityMethod = typeof(ModelBuilder).GetMethods().First(f => f.Name == "Entity");
var ent = entityMethod.MakeGenericMethod(type).Invoke(modelBuilder, new object[] { });  // add the new History type to the model
var haskey = ent.GetType().GetMethods().FirstOrDefault(m => m.Name == "HasKey");
var param = Expression.Parameter(type, "k");  List<MemberExpression> args = new List<MemberExpression>();
var pk = historable.FindPrimaryKey();
foreach (var prop in pk.Properties)  // we add in the same key properties as the table that we are tracking
    args.Add(Expression.PropertyOrField(param, prop.Name));

args.Add(Expression.PropertyOrField(param, "ChangeDate"));  // and then also add in ChangeDate as part of the PK to keep it unique





Aucun commentaire:

Enregistrer un commentaire