win7user10 / Laraue.EfCoreTriggers

Library to write triggers in C# with EF.Core
MIT License
111 stars 20 forks source link

Table splitting seems to cause triggers unable to be created #90

Open JarRami opened 11 months ago

JarRami commented 11 months ago

If I have tables setup for table splitting like

public class IntEntity {
    public int ID { get; set; }
    public int Value { get; set; }

    public virtual EntityDetails Details { get; set; }
}
public class EntityDetails {
    public int ID { get; set; }
    public string Text { get; set; }
}

and

public class EntityHistory {
    public int ID { get; set; }
    public int Value { get; set; }
    public string Text { get; set; }
}

and on the contexts' OnModelCreating method I setup the context like this

modelBuilder.Entity<IntEntity>(eb => {
    eb.ToTable("IntEntity")
        .HasKey(e => e.ID);

    eb.HasOne(e => e.Details)
        .WithOne()
        .HasPrincipalKey<IntEntity>(e => e.ID)
        .HasForeignKey<EntityDetails>(d => d.ID);

    eb.AfterInsert(trigger => trigger
        .Action(action => action
            .Insert<EntityHistory>(tableRefs => new EntityHistory() {
                Value = tableRefs.New.Value,
                Text = tableRefs.New.Details.Text
            })
        )
    );
});

modelBuilder.Entity<EntityDetails>(db => {
    db.ToTable("IntEntity");
});

modelBuilder.Entity<EntityHistory>(db => {
    db.ToTable("EntityHistory");
});

If I then try to create a new IntEntity with some Details and save it to the database, the program hits an exception "Column Text was not found in EFCoreTriggerTest.IntEntity" with a stacktrace

     at Laraue.EfCoreTriggers.Common.SqlGeneration.EfCoreDbSchemaRetriever.GetColumn(Type type, MemberInfo memberInfo)
   at Laraue.EfCoreTriggers.Common.SqlGeneration.EfCoreDbSchemaRetriever.GetColumnName(Type type, MemberInfo memberInfo)
   at Laraue.EfCoreTriggers.Common.SqlGeneration.SqlGenerator.GetColumnSql(Type type, MemberInfo memberInfo, ArgumentType argumentType)
   at Laraue.EfCoreTriggers.Common.Visitors.ExpressionVisitors.MemberExpressionVisitor.GetColumnSql(Type tableType, MemberInfo columnMember, ArgumentType argumentType)
   at Laraue.EfCoreTriggers.Common.Visitors.ExpressionVisitors.MemberExpressionVisitor.GetColumnSql(MemberExpression memberExpression, MemberInfo parentMember, VisitedMembers visitedMembers)
   at Laraue.EfCoreTriggers.Common.Visitors.ExpressionVisitors.MemberExpressionVisitor.Visit(MemberExpression memberExpression, ArgumentType argumentType, VisitedMembers visitedMembers)
   at Laraue.EfCoreTriggers.Common.Visitors.ExpressionVisitors.MemberExpressionVisitor.Visit(MemberExpression expression, VisitedMembers visitedMembers)
   at Laraue.EfCoreTriggers.Common.Visitors.ExpressionVisitors.ExpressionVisitorFactory.Visit[TExpression](TExpression expression, VisitedMembers visitedMembers)
   at Laraue.EfCoreTriggers.Common.Visitors.ExpressionVisitors.ExpressionVisitorFactory.<>c__DisplayClass4_0.<VisitAndRememberMember>b__0()
   at Laraue.EfCoreTriggers.Common.Visitors.ExpressionVisitors.VisitingInfoExtensions.ExecuteWithChangingMember[T](VisitingInfo info, MemberInfo memberInfo, Func`1 action)
   at Laraue.EfCoreTriggers.Common.Visitors.ExpressionVisitors.ExpressionVisitorFactory.VisitAndRememberMember(MemberExpression expression, VisitedMembers visitedMembers)
   at Laraue.EfCoreTriggers.Common.Visitors.ExpressionVisitors.ExpressionVisitorFactory.Visit(Expression expression, VisitedMembers visitedMembers)
   at Laraue.EfCoreTriggers.Common.Visitors.SetExpressionVisitors.SetMemberInitExpressionVisitor.<>c__DisplayClass3_1.<Visit>b__3()
   at Laraue.EfCoreTriggers.Common.Visitors.ExpressionVisitors.VisitingInfoExtensions.ExecuteWithChangingMember[T](VisitingInfo info, MemberInfo memberInfo, Func`1 action)
   at Laraue.EfCoreTriggers.Common.Visitors.SetExpressionVisitors.SetMemberInitExpressionVisitor.<>c__DisplayClass3_0.<Visit>b__0(MemberBinding memberBinding)
   at System.Linq.Enumerable.SelectIListIterator`2.MoveNext()
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector)
   at Laraue.EfCoreTriggers.Common.Visitors.SetExpressionVisitors.SetMemberInitExpressionVisitor.Visit(MemberInitExpression expression, VisitedMembers visitedMembers)
   at Laraue.EfCoreTriggers.Common.Visitors.SetExpressionVisitors.MemberInfoVisitorFactory.Visit[TExpression](TExpression expression, VisitedMembers visitedMembers)
   at Laraue.EfCoreTriggers.Common.Visitors.SetExpressionVisitors.MemberInfoVisitorFactory.Visit(Expression expression, VisitedMembers visitedMembers)
   at Laraue.EfCoreTriggers.Common.Visitors.SetExpressionVisitors.SetLambdaExpressionVisitor.Visit(LambdaExpression expression, VisitedMembers visitedMembers)
   at Laraue.EfCoreTriggers.Common.Visitors.SetExpressionVisitors.MemberInfoVisitorFactory.Visit[TExpression](TExpression expression, VisitedMembers visitedMembers)
   at Laraue.EfCoreTriggers.Common.Visitors.SetExpressionVisitors.MemberInfoVisitorFactory.Visit(Expression expression, VisitedMembers visitedMembers)
   at Laraue.EfCoreTriggers.Common.Visitors.TriggerVisitors.Statements.InsertExpressionVisitor.Visit(LambdaExpression expression, VisitedMembers visitedMembers)
   at Laraue.EfCoreTriggers.Common.Visitors.TriggerVisitors.TriggerInsertActionVisitor.Visit(TriggerInsertAction triggerAction, VisitedMembers visitedMembers)
   at Laraue.EfCoreTriggers.Common.Visitors.TriggerVisitors.TriggerActionVisitorFactory.Visit[T](T triggerAction, VisitedMembers visitedMembers)
   at Laraue.EfCoreTriggers.Common.Visitors.TriggerVisitors.TriggerActionVisitorFactory.Visit(ITriggerAction triggerAction, VisitedMembers visitedMembers)
   at Laraue.EfCoreTriggers.Common.Visitors.TriggerVisitors.BaseTriggerActionsGroupVisitor.<>c__DisplayClass2_0.<Visit>b__0(ITriggerAction action)
   at System.Linq.Enumerable.SelectListIterator`2.ToArray()
   at Laraue.EfCoreTriggers.Common.Visitors.TriggerVisitors.BaseTriggerActionsGroupVisitor.Visit(TriggerActionsGroup triggerActionsGroup, VisitedMembers visitedMembers)
   at Laraue.EfCoreTriggers.Common.Visitors.TriggerVisitors.TriggerActionVisitorFactory.Visit[T](T triggerAction, VisitedMembers visitedMembers)
   at Laraue.EfCoreTriggers.Common.Visitors.TriggerVisitors.TriggerActionVisitorFactory.Visit(ITriggerAction triggerAction, VisitedMembers visitedMembers)
   at Laraue.EfCoreTriggers.SqlServer.SqlServerTriggerVisitor.<>c__DisplayClass7_0.<GenerateCreateTriggerSql>b__0(TriggerActionsGroup action)
   at System.Linq.Enumerable.SelectListIterator`2.ToArray()
   at Laraue.EfCoreTriggers.SqlServer.SqlServerTriggerVisitor.GenerateCreateTriggerSql(ITrigger trigger)
   at Laraue.EfCoreTriggers.Common.Migrations.MigrationsExtensions.ConvertTriggerAnnotationsToSql(ITriggerVisitor triggerVisitor, IModel model)
   at Laraue.EfCoreTriggers.Common.Migrations.TriggerModelDiffer.AddTriggerOperations(IEnumerable`1 operations, IRelationalModel source, IRelationalModel target)
   at Laraue.EfCoreTriggers.Common.Migrations.MigrationsModelDiffer.GetDifferences(IRelationalModel source, IRelationalModel target)
   at Microsoft.EntityFrameworkCore.Storage.RelationalDatabaseCreator.GetCreateTablesCommands(MigrationsSqlGenerationOptions options)
   at Microsoft.EntityFrameworkCore.Storage.RelationalDatabaseCreator.CreateTables()
   at Microsoft.EntityFrameworkCore.Storage.RelationalDatabaseCreator.EnsureCreated()
   at Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.EnsureCreated()

No tables are created in this case when before saving the entity I call ctx.Database.EnsureCreated(). This seems to be an issue with this library because if I comment out setting the Text property on the history entity in the Insert trigger, everything works, the IntEntity is saved with details and an EntityHistory row is created. I tested this on version 7.1.1 against a SQL Server instance.