Код: Выделить всё
public class EntityAdder where TDbContext : DbContext
{
private readonly TDbContext _dbContext;
private readonly MyOptions _options;
public EntityAdder(TDbContext dbContext,
MyOptionsProvider optionsProvider)
{
_dbContext = dbContext;
_options = optionsProvider.GetOptions();
}
public async Task AddEntities(Dictionary entities)
{
var dbSets = typeof(TDbContext)
.GetProperties()
.Where(x => x.PropertyType.IsGenericType)
.Select(x => new DbSetInfo
{
DbSet = x.GetGetMethod()!.Invoke(_dbContext, [])!,
DbSetProperty = x,
AddMethod = x.PropertyType.GetMethod("Add")!
})
.ToList();
foreach (var (entity, pool) in entities)
{
var dbSet = dbSets.Single(x => x.DbSetProperty.PropertyType.GetGenericArguments()[0] == entity.EntityType);
if (_options.OverrideExistingData)
{
clearDbSet(dbSet);
}
foreach (var entityObject in pool)
{
dbSet.AddMethod.Invoke(dbSet.DbSet, [entityObject]);
}
}
await _dbContext.SaveChangesAsync();
}
private void clearDbSet(DbSetInfo dbSet)
{
MethodInfo removeRangeMethod = dbSet.DbSetProperty.PropertyType
.GetMethods()
.Where(x => x.Name == "RemoveRange")
.ElementAt(1);
removeRangeMethod.Invoke(dbSet.DbSet, [dbSet.DbSet]);
}
class DbSetInfo
{
public object DbSet { get; set; }
public PropertyInfo DbSetProperty { get; set; }
public MethodInfo AddMethod { get; set; }
}
}
Код: Выделить всё
public class TestEntity1
{
public int ID { get; set; }
public int Value { get; set; }
public string Value2 { get; set; }
public bool Value3 { get; set; }
public TestEntity2? Entity2 { get; set; }
}
public class TestEntity2
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string ID { get; set; }
public string Value { get; set; }
public string Value2 { get; set; }
public TestEntity1? Entity1 { get; set; }
public int? Entity1ID { get; set; }
}
Код: Выделить всё
DbContext:
public class TestContext : DbContext
{
public TestContext() { }
public TestContext(DbContextOptions options) : base(options) { }
public DbSet Entity1 { get; set; }
public DbSet Entity2 { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder builder)
{
if (builder.IsConfigured) return;
builder.EnableSensitiveDataLogging();
builder.UseInMemoryDatabase("TestDatabase");
}
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity()
.HasKey(e => e.ID);
builder.Entity()
.HasKey(e => e.ID);
builder.Entity()
.HasOne(e => e.Entity2)
.WithOne(e => e.Entity1)
.HasForeignKey(e => e.Entity1ID);
}
}
Код: Выделить всё
EntityInfoКласс
Идентификатор первого экземпляра в значение пула равно 0, но при попытке добавить его в dbSet оно внезапно меняется на 1. Затем при добавлении следующего экземпляра с идентификатором 1 выдается исключение, поскольку идентификатор первого экземпляра был изменен на 1:
Экземпляр типа сущности «TestEntity1» невозможно отследить, поскольку другой экземпляр со значением ключа «{ID: 1}» уже отслеживается. При присоединении существующих объектов убедитесь, что присоединен только один экземпляр объекта с заданным значением ключа.
Первый шаг итерации:

После добавления:

Почему это происходит и как это исправить?
Подробнее здесь: https://stackoverflow.com/questions/785 ... another-in