English 中文(简体)
EF 核心: 第xxxx类实体的例子无法跟踪...... 通过增加儿童来更新父母记录错误
原标题:EF Core: The instance of entity type xxxx cannot be tracked... Error when updating parent record by adding children

我已陷入了非常独特的错误,并将非常感激。 目前,我正在使用蚊帐7进行新的双赢应用。 我们正在使用EF核心,与MS Acces DB文档(别无选择)相结合。 我已经设立了一个机构,询问现有的商业发展实体反对,然后向它增加儿童OtcVariation MarginRecords。 我在单位和一体化测试(XUnit)中专门从事这项工作。 这是我遇到一个问题的融合测试: 直到几天前,这项服务一直徒劳无益地运作,拯救了在非行档案中预期的所有记录。 两天前,我开始收到这一错误:

系统. InvalidOperation 例外: 无法跟踪实体类型OtcVariationMarginRecord的事例,因为另一个对{Id }具有相同关键价值的案子已经跟踪。 在保留现有实体时,确保只附上一个具有一定关键价值的实体。 考虑使用DbContextOptionsBuilder. EnableSensitive 数据记录显示,关键价值相互冲突。

What I ve tried:

  • We recently updated our Microsoft.EntityFrameworkCore.Tools package from 7.0.9 to 7.0.10. I tried rolling it back, but the issue persisted. Nothing else has changed recently.
  • I created simple Parent/Child model objects with minimal properties, ran the migrations, and received the same error when trying update an existing parent by adding children. Thus the issue is not with my margin models.
  • We inject a complicated _dbContextService wrapper/interface (not created by me) that handles all sorts of audit trail updating. I have completely removed it and instead reference the concrete dbContext. Did not fix.
  • I am relatively new to EF core, so I read everything here. I tried shortening the life of the dbContext (see code below) but the same error returned.
  • I also tried this, this, and this. Using AsNoTracking() just results in no OtcVariationMarginRecord records being saved to the DB. Same with _context.ChangeTracker.Clear().

I feel absolutely stumped, and hope someone here can point out an obvious flaw in my code. Many thanks.

Entity models:

[Index(nameof(Date), IsUnique = true)]
public class BusinessDate : BaseEntity
{
    public DateTime Date { get; set; }
    public List<OtcVariationMarginRecord> OtcVariationMarginRecords { get; set; } = new();
}

public class OtcVariationMarginRecord : BaseEntity
{   
    public decimal BaseCurrencyExposure { get; set; }
    public CurrencyCode BaseCurrency { get; set; }
    public decimal TransferAmount { get; set; }
    public MarginCallNature CallNature { get; set; }
    public MarginDirection Direction { get; set; }
    public decimal RoundedTransferAmount { get; set; }

    // i have removed a bunch of properties as part of my trouble shooting.
}
public abstract class BaseEntity : IBaseEntity
{
    [Key]
    public int Id { get; set; }
    public virtual RecordStatus Status { get; set; }
    [NotMapped]
    public DateTime? LastModifiedDateTimeUtc { get; set; }
    [NotMapped]
    public int? LastModifiedBy { get; set; }
    [NotMapped]
    public string? LastModifiedByName { get; set; }
}

Simplified usage:

private EfCoreTrackingTestContext _context;

public async Task GenerateMarginRecordsAsync(DateTime asOfDate)
{
    // i instantiate here instead of inject just for troubleshooting
    await using (_context = InstantiateContext())
    {
        var businessDate = await _context
            .BusinessDates
            //.AsNoTracking() // this resulted in nothing being saved
            .Include(bd => bd.OtcVariationMarginRecords)            
            .SingleOrDefaultAsync(bd => bd.Date == asOfDate)
            .ConfigureAwait(false);

        // nothing here touches the db nor entities that already exist
        var newMarginRecords = CalculationLogic();

        targetBusinessDate.OtcVariationMarginRecords.AddRange(newMarginRecords);
        
        // error thrown here
        await _context.SaveChangesAsync().ConfigureAwait(false);        
    }
}
private static EfCoreTrackingTestContext InstantiateContext()
{
    var optionsBuilder = new DbContextOptionsBuilder<EfCoreTrackingTestContext>();
    var options = optionsBuilder
        .UseJet(TestDbConfig.ConnectionString.IntegrationTestMarginDb)
        .Options;
    return new EfCoreTrackingTestContext(options);
}

Update 2023-08-31

感谢大家的答复。 问题依然存在。 有人要求我张贴一些计算逻辑,因此,我的发言包括以下简化版本。 问题的其他答案是:

  • Q: Can you confirm whether it actually stopped working after upgrading the EF Core version, or might that have been a coincidental "around the same time"?
  • A: I cannot confirm, I am treating it more as a clue. I believe I was able to run the integration tests successfully for a couple days following the update. Could be related, could be coincidental.

  • Q: What provider are you using for the MSAccess connection?
  • A: Provider=Microsoft.ACE.OLEDB.12.0;

  • Q: in the Access database is the Id column in the OtcVariationMarginRecord table set to an Autonumber?
  • A: Confirmed that it is.

  • Q: Is that the actual table name, because if not, are there any OnModelCreating or IEntityTypeConfiguration implementations set up for configuring the entity to table relationship?
  • A: The name of the table is OtcVariationMarginRecords. I have included OnModelCreating code below.

此外,我还尝试了法比奥的建议,但我仍在犯同样的错误。

这里还有一些法典:

private ICollection<OtcVariationMarginRecord>  CalculationLogic()
 {

    // Simplified for brevity. Removed all CRUD operations besides create, as that s 
    // what I ve done during troubleshooting anyway.
    var toAdd = new List<OtcVariationMarginRecord>();

     // derived from raw data retrieved from vendor api (unrelated to internal db)
     IEnumerable<OtcMarginCounterparty> marginCounterparties = GetMarginCounterparties();
     // derived from raw data retrieved from vendor api (unrelated to internal db)
     IEnumerable<Trade> marginTrades = GetMarginTrades();
     // loop through all counterparties and check exposure against limits.
     foreach (var counterparty in marginCounterparties)
     {         
         var counterpartyTrades = marginTrades.Where(t => t.Counterparty == counterparty.Name);         
         var calculatedVm = Calculate(counterpartyTrades, counterparty);

         toAdd.Add(calculatedVm);
     }

     return toAdd;
 }
 private OtcVariationMarginRecord Calculate(
    IEnumerable<Trade> counterpartyTrades,
    OtcMarginCounterparty counterparty)
 {
    // basically just math here to determine decimal and enum values...

    return new OtcVariationMarginRecord
    {
        Direction = direction,
        CallNature = nature,
        TransferAmount = transferAmount,
        RoundedTransferAmount = roundedCallAmount,
        Status = RecordStatus.Pending,
        BaseCurrencyExposure = counterpartyExposureBaseCcy,
        BaseCurrency = portfolioCurrency
    };
 }

与移民有关的法典:

public class EfCoreTrackingTestContext : DbContext
{    
    public DbSet<BusinessDate> BusinessDates => Set<BusinessDate>();
    public DbSet<OtcVariationMarginRecord> OtcVariationMarginRecords => Set<OtcVariationMarginRecord>();

    public EfCoreTrackingTestContext(DbContextOptions options) : base(options)
    {

    }
    protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
    {
        base.ConfigureConventions(configurationBuilder);
        configurationBuilder.Properties<string>().HaveMaxLength(255);
        configurationBuilder.Properties<decimal>().HaveColumnType("decimal(18, 2)");
    }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        //Make EF core not create a table for BaseEntity abstraction
        builder.Entity<BaseEntity>().UseTpcMappingStrategy();

        builder.Entity<BusinessDate>()
            .HasMany(s => s.OtcVariationMarginRecords)
            .WithOne()
            .OnDelete(DeleteBehavior.Restrict);   
    }

}

Second Update 2023-08-31

在继续面临麻烦的情况下,我从MS Access转向Sql Express,相应地更新了我的DbContextFactory,并造成了新的移民。 在这样做之后,我原法典的所有内容都意味着,所有CRUD业务都是预期的,显然没有任何跟踪错误。 因此,我如何通过欧洲核心连接管理系统接入,显然是错误的。 我不能不ath。

问题回答

在OtcVariation MarginRe Table, EF将自动增加与家庭企业日期有关的领域(即母体表格),因为它是一个儿童表。 你可以核实(我受审)。 最好修改这一类别,增加科索沃武装部队,这样,我们就可以在法典后面提及:

public class OtcVariationMarginRecord : BaseEntity
{
    public decimal BaseCurrencyExposure { get; set; }
    public CurrencyCode BaseCurrency { get; set; }
    public decimal TransferAmount { get; set; }
    public MargingCallNature CallNature { get; set; }
    public MargingDirection Direction { get; set; }
    public decimal RoundedTransferAmount { get; set; }
    public int BusinessDateId { get; set; }
    public BusinessDate BusinessDate { get; set; }           
}

最后, 你可以尝试这一法典:

public async Task GenerateMarginRecordsAsync(DateTime asOfDate)
{                                                
    await using (_context = InstantiateContext())
    {
        var targetbusinessDate = await _context
            .BusinessDates                                            
            .SingleOrDefaultAsync(bd => bd.Date == asOfDate)
            .ConfigureAwait(false);

        int myId = targetbusinessDate.Id;
        _context.Entry(targetbusinessDate).State = EntityState.Unchanged;

        var newMarginRecords = CalculationLogic();
      
        foreach (OtcVariationMarginRecord mr in newMarginRecords)
        {
            mr.Id = 0;
            mr.BusinessDateId = myId;
            _context.OtcVariationMarginRecords.Add(mr);
        }
                        
        await _context.SaveChangesAsync().ConfigureAwait(false);
    }
}

I added the new OtcVariationMarginRecords directly into their table, without including the existing ones in the parent table. I hope, this will help You.

SOLVED

问题是:

// problem code 1
builder.Entity<BaseEntity>().UseTpcMappingStrategy();

结合使用体格作为主要关键因素:

// problem code 2
public abstract class BaseEntity : IBaseEntity
{
    [Key]
    public int Id { get; set; }
}

更多信息here

将战略改为:TPT,或将主要关键数据Type改为“Guid”都解决了这一问题。 我们选择把所有主要关键数据表改为准则,因为这似乎是一个更可衡量的标准。

// updated code
public abstract class BaseEntity : IBaseEntity
{
    [Key]
    public Guid Id { get; set; }
}




相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签