Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Owned types in separate table does not work #114

Closed
StevenRasmussen opened this issue Dec 19, 2018 · 7 comments
Closed

Owned types in separate table does not work #114

StevenRasmussen opened this issue Dec 19, 2018 · 7 comments

Comments

@StevenRasmussen
Copy link

I see that 'Owned' types is listed as supported but perhaps only with table splitting? When I use an owned type that is in a separate table it doesn't appear to be working. Here is the code to configure the owned entity:

modelBuilder.Entity<DmTransaction>(entity =>
{
     entity.OwnsOne(x => x.APPayment, a =>
     {
          a.ToTable(nameof(APPaymentExt));
          a.HasForeignKey(f => f.Transaction);
     });
}
@borisdj
Copy link
Owner

borisdj commented Dec 20, 2018

Yes, currently are supported only 'Owned' types mapped by convention to the same table as the owner.
For now you could change child to be regular 1-1 table instead of being owned type, and then implement method that does 2 BulkInsert, first parent list and then child list.
(there is example in the README of parent-child FK related tables).
I will put Enhancement tag for this feature.

@ChristopherHaws
Copy link

Owned types that have seperate tables currently causes the BulkInsertOrUpdateOrDeleteAsync call to fail with a null reference exception:

System.NullReferenceException
  HResult=0x80004003
  Message=Object reference not set to an instance of an object.
  Source=EFCore.BulkExtensions
  StackTrace:
   at EFCore.BulkExtensions.TableInfo.LoadData[T](DbContext context, IList`1 entities, Boolean loadOnlyPKColumn)
   at EFCore.BulkExtensions.TableInfo.CreateInstance[T](DbContext context, IList`1 entities, OperationType operationType, BulkConfig bulkConfig)
   at EFCore.BulkExtensions.DbContextBulkTransaction.ExecuteAsync[T](DbContext context, IList`1 entities, OperationType operationType, BulkConfig bulkConfig, Action`1 progress)
   at EFCore.BulkExtensions.DbContextBulkExtensions.BulkInsertOrUpdateOrDeleteAsync[T](DbContext context, IList`1 entities, BulkConfig bulkConfig, Action`1 progress)

Can the library at least ignore the owned type property so that we can do the bulk update as a 2nd call (similar to how it would work if it wasn't an owned type)?

@IT-CASADO
Copy link

IT-CASADO commented Oct 14, 2019

Today, I encountered the same problem. I tried to set BulkConfig.PropertiesToExclude, but this doesn't change anything. I reviewed the code for EF Core 2.2, and can see that PropertiesToExclude/PropertiesToInclude are not applied to Owned Types.

Would help, if at least we can ignore such owned properties by setting PropertiesToExclude/PropertiesToInclude.

@ctolkien
Copy link

Also hitting this problem here.

@sandrohanea
Copy link

The same problem happens if OwnsMany is used but in this case, we cannot use @borisdj's approach as we cannot map them in the same table as the relation is 1-to-many.

@borisdj
Copy link
Owner

borisdj commented Mar 20, 2021

This can now, v3.4.6+, be achieved with 2 calls and config for mutual excluding Properties from other table.
Here is example on entities from the Test, only changed to be owned in separated tables:

modelBuilder.Entity<ChangeLog>().OwnsOne(p => p.Audit, a => { a.ToTable(nameof(Audit)); });
public class ChangeLog
{
  public int ChangeLogId { get; set; }
  public string Description { get; set; }
  public Audit Audit { get; set; }
}

[Owned]
public class Audit
{
  public string ChangedBy { get; set; }
  public bool IsDeleted { get; set; }
  public InfoType InfoType { get; set; } // InfoType is Enum
}
var entities = new List<ChangeLog>();
for (int i = 1; i <= 1000; i++)
{
  entities.Add(new ChangeLog
  {
    Description = "Dsc " + i,
    Audit = new Audit
    {
      ChangedBy = "User" + 1
      InfoType = InfoType.InfoTypeA
    }
});

var bulkConfig = new BulkConfig
{
  SetOutputIdentity = true, // required to load Id that are need for second Bulk call into owned table
  PropertiesToExclude = new List<string> {
    $"{nameof(Audit)}.{nameof(Audit.ChangedBy)}",
    $"{nameof(Audit)}.{nameof(Audit.IsDeleted)}",
    $"{nameof(Audit)}.{nameof(Audit.InfoType)}",
  }
};
var bulkConfigOwned = new BulkConfig
{
  CustomDestinationTableName = nameof(Audit), // set name of Owned table as Destination
  PropertiesToExclude = new List<string> { nameof(ChangeLog.Description) },
};

using (var transaction = context.Database.BeginTransaction())
{
    context.BulkInsert(entities, bulkConfig);
    context.BulkInsert(entities, bulkConfigOwned);
    transaction.Commit();
}

@crperez5
Copy link

What about One-To-Many relationships? I am getting the Object reference not set to an instance of an object exception using an adapted version of your example above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants