如何解决再次运行迁移时出错似乎需要处置通用存储库,我不知道该如何处理
请忍受我,我真的在这里挣扎。
我对依赖注入的EF Core相对较新。我来自asp.net的旧世界,其中包含更新类等,但是我想尝试并使用依赖注入。由于我们的旧数据库也需要迁移到新结构,因此我认为一个不错的第一个应用程序将是编写一个将使用依赖项注入的应用程序。我决定使用Blazor作为我们的最终代码库。
有两个数据库,一个称为QOnT,一个称为iSele。我正在使用包括https://ngohungphuc.wordpress.com/2018/05/01/generic-repository-pattern-in-asp-net-core/和https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application在内的许多网站将数据从QOnT迁移到iSele-我创建了两个通用存储库。一种用于QOnT表,另一种将作为最终应用程序回购。我还为两者创建了通用工作单元。
泛型与Tony的Tech&Language Blog或https://ngohungphuc.wordpress.com/大致相同,但有一项更改可以满足以下事实:我需要插入和更新标识字段中的项目。所以我创建了一个通用例程,该例程禁用身份检查,然后执行插入操作并将其重新打开。我已将其粘贴在下面:
public T AddWithIDOn(T entity,string TableName)
{
_loggerManager.LogDebug($"FancyRepo -> AddWithIDOn {typeof(T)},enttity {entity.ToString()},Table: {TableName} ");
_context.Database.OpenConnection();
try
{
_context.Database.ExecutesqlRaw($"SET IDENTITY_INSERT {TableName} ON");
_context.Set<T>().Add(entity);
_context.SaveChanges();
_context.Database.ExecutesqlRaw($"SET IDENTITY_INSERT {TableName} OFF");
}
catch (Exception ex)
{
_loggerManager.LogInfo($"!!!Error!!! FancyRepo -> AddWithIDOn error: {ex.Message}");
}
finally
{
_context.Database.CloseConnection();
}
return entity;
}
这很好。
在Startup.cs中,我添加了DbContext和工作单元
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddDbContextPool<ApplicationDbContext>(options =>
{
options.UsesqlServer(Configuration.GetConnectionString("iSeleConnection"));
options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
options.EnableSensitiveDataLogging(true);
});
services.AddDbContext<QOnTDbContext>(qontoptions =>
{
qontoptions.UsesqlServer(Configuration.GetConnectionString("QOnTConnection"));
});
//services.AddScoped(typeof(IQOnTGenericRepository<>),typeof(QOnTGenericRepository<>));
services.AddScoped(typeof(IQOnTUnitOfWork),typeof(QOnTUnitOfWork));
// services.AddScoped(typeof(IGenericRepository<>),typeof(IGenericRepository<>));
services.AddScoped(typeof(IUnitOfWork),typeof(UnitOfWork));
// logger
services.AddSingleton<ILoggerManager,LoggerManager>();
}
您将看到我已注释掉这些服务。为重新发布而添加的范围是Unitofwork创建它们的。
然后,我有一个“代码隐藏”或我的剃须刀背后的Migrate客户(称为CompnentBase)
所以
public partial class MigrateCustomersBase : ComponentBase
在其中注入两个UnitOfWorks
[Inject]
private IQOnTUnitOfWork _QOnTUnitOfWork { get; set; }
[Inject]
private IUnitOfWork _iSeleUnitOfWork { get; set; }
我在表单上有一个按钮,单击该按钮即可进行迁移:
IQOnTGenericRepository<CustomerTypeTbl> QOnTCustomerTypeTbl = _QOnTUnitOfWork.Repository<CustomerTypeTbl>();
ICollection<CustomerTypeTbl> QOnTCustomerTypes = QOnTCustomerTypeTbl.GetAll();
foreach (var srcCusType in QOnTCustomerTypes)
{
CustomerType tgtCusType = _iSeleUnitOfWork.Repository<CustomerType>().Find(ct => ct.CustomerTypeID == srcCusType.CustTypeId);
if (tgtCusType == null)
{
Logger.LogDebug($" *Inserting CustomerType with id: {srcCusType.CustTypeId} and name {srcCusType.CustTypeDesc}");
_iSeleUnitOfWork.Repository<CustomerType>().AddWithIDOn(new CustomerType
{
CustomerTypeID = srcCusType.CustTypeId,CustomerTypeName = srcCusType.CustTypeDesc,HasExtendedOptions = false,Notes= string.Format("Migrated from QOnT.CustomerTypeTbl {0:d}",DateTime.UtcNow.Date)
},"iSele.CustomerTypes");
}
else
{
tgtCusType.CustomerTypeName = srcCusType.CustTypeDesc;
tgtCusType.HasExtendedOptions = false;
tgtCusType.Notes = string.Format("Migrated from QOnT.CustomerTypeTbl {0:d}",DateTime.UtcNow.Date);
Logger.LogDebug($" *Updating Area with id: {tgtCusType.CustomerTypeID} and name {tgtCusType.CustomerTypeName}");
_iSeleUnitOfWork.Repository<CustomerType>().Update(tgtCusType);
}
}
}
所以毕竟这是我的问题。好吧,我第一次运行代码时一切正常。但是,如果再次单击按钮(调用代码),则会出现错误
无法跟踪实体类型“ CustomerType”的实例,因为已经跟踪了另一个键值为“ {CustomerTypeID:1}”的实例。附加现有实体时,请确保仅附加一个具有给定键值的实体实例。
在我看来,这似乎存在多个UnitOfWorks。如果我离开该页面,然后返回,它将再次起作用。这只是第二次单击该按钮,它不起作用。我在做什么错,我该如何处置UnitOfWork,是否需要刷新页面或其他内容?
解决方法
所以我停止使用依赖项注入,按如下所示修改了单击时调用的函数:
var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
optionsBuilder.UseSqlServer(ConString);
optionsBuilder.EnableSensitiveDataLogging(true);
optionsBuilder.EnableDetailedErrors(true);
ApplicationDbContext _iSeleDbContext = new ApplicationDbContext(optionsBuilder.Options);
UnitOfWork _iSeleUnitOfWork = new UnitOfWork(_iSeleDbContext,Logger);
IQOnTFancyGenericRepository<CustomerTypeTbl> QOnTCustomerTypeTbl = _QOnTUnitOfWork.Repository<CustomerTypeTbl>();
ICollection<CustomerTypeTbl> QOnTCustomerTypes = QOnTCustomerTypeTbl.GetAll();
foreach (var srcCusType in QOnTCustomerTypes)
{
CustomerType tgtCusType = _iSeleUnitOfWork.Repository<CustomerType>().Find(ct => ct.CustomerTypeID == srcCusType.CustTypeId);
if (tgtCusType == null)
{
//await
Logger.LogDebug($" *Inserting CustomerType with id: {srcCusType.CustTypeId} and name {srcCusType.CustTypeDesc}");
_iSeleUnitOfWork.Repository<CustomerType>().AddWithIDOn(new CustomerType
{
CustomerTypeID = srcCusType.CustTypeId,CustomerTypeName = srcCusType.CustTypeDesc,HasExtendedOptions = false,Notes = string.Format("Migrated from QOnT.CustomerTypeTbl {0:d}",DateTime.UtcNow.Date)
},"iSele.CustomerTypes");
}
else
{
tgtCusType.CustomerTypeName = srcCusType.CustTypeDesc;
tgtCusType.HasExtendedOptions = false;
tgtCusType.Notes = string.Format("Migrated from QOnT.CustomerTypeTbl {0:d}",DateTime.UtcNow.Date);
Logger.LogDebug($" *Updating Area with id: {tgtCusType.CustomerTypeID} and name {tgtCusType.CustomerTypeName}");
_iSeleUnitOfWork.Repository<CustomerType>().Update(tgtCusType);
}
}
_iSeleUnitOfWork.Dispose();
所以我现在迷路了。依赖注入似乎很烂。但是为什么互联网上的所有人都推荐它。这不是实用的解决方案。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。