我正在努力将实体框架添加到我们的Web应用程序asp.net MVC 5中,但是我很难保存更改并添加到数据库中。我使用通用的BaseRepository设置了UnitOfWork,并且尝试了一些尝试来使其正常工作。首先,我以为我可以使用AutoFac将我的仓库注入UnitOfWork,就像这样
public UnitOfWork(IServiceItem serviceItem
, ITechServiceItem techServiceItem
, ITechnicianTime technicianTime
, ISproc sproc
, IRepairOrder repairOrder
, ICustomer customer
, IRepairOrderStatus repairOrderStatus
, IRepairOrderUnit repairOrderUnit
, IFiles files
, IPartInventory partInventory
, IRepairOrderItems repairOrderItems
)
{
RepairOrderItems = repairOrderItems;
PartInventory = partInventory;
Files = files;
RepairOrderUnit = repairOrderUnit;
RepairOrderStatus = repairOrderStatus;
RepairOrder = repairOrder;
Customer = customer;
Sproc = sproc;
ServiceItem = serviceItem;
TechServiceItem = techServiceItem;
TechnicianTime = technicianTime;
}
我的BaseRepo就像
public class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
protected DataDbContext _db;
public class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
protected DataDbContext _db;
internal void GetData()
{
if (_db == null)
{
string accountNumber = HttpContext.Current.User.Identity.GetCompanyAccountNumber();
var connectionToken = ConfigurationManager.AppSettings["LoginSplitToken"];
_db = new DataDbContext(ConfigurationManager.ConnectionStrings["NameOfConnString"].ConnectionString.Replace(connectionToken, accountNumber));
}
}
public TEntity Get(int id)
{
return _db.Set<TEntity>().Find(id);
}
public IEnumerable<TEntity> GetAll()
{
return _db.Set<TEntity>().ToList();
}
public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
{
return _db.Set<TEntity>().Where(predicate);
}
public void Add(TEntity entity)
{
_db.Set<TEntity>().Add(entity);
}
public void AddRange(IEnumerable<TEntity> entities)
{
_db.Set<TEntity>().AddRange(entities);
}
public void Remove(TEntity entity)
{
_db.Set<TEntity>().Remove(entity);
}
public void RemoveRange(IEnumerable<TEntity> entities)
{
_db.Set<TEntity>().RemoveRange(entities);
}
public int CompleteData()
{
return _db.SaveChanges();
}
public TEntity Get(int id)
{
return _db.Set<TEntity>().Find(id);
}
public IEnumerable<TEntity> GetAll()
{
return _db.Set<TEntity>().ToList();
}
public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
{
return _db.Set<TEntity>().Where(predicate);
}
public void Add(TEntity entity)
{
_db.Set<TEntity>().Add(entity);
}
public void AddRange(IEnumerable<TEntity> entities)
{
_db.Set<TEntity>().AddRange(entities);
}
public void Remove(TEntity entity)
{
_db.Set<TEntity>().Remove(entity);
}
public void RemoveRange(IEnumerable<TEntity> entities)
{
_db.Set<TEntity>().RemoveRange(entities);
}
public int CompleteData()
{
return _db.SaveChanges();
}
}
和我的StartUp.Configuration
public void Configuration(IAppBuilder app)
{
var builder = new ContainerBuilder();
HttpConfiguration config = GlobalConfiguration.Configuration;
// REGISTER DEPENDENCIES
builder.RegisterType<EverLogicDbContext>().AsSelf().InstancePerRequest();
builder.RegisterType<ApplicationUserManager>().AsSelf().InstancePerRequest();
builder.RegisterType<ApplicationSignInManager>().AsSelf().InstancePerRequest();
builder.Register(c => HttpContext.Current.GetOwinContext().Authentication).InstancePerRequest();
builder.Register(c => HttpContext.Current.User).InstancePerRequest();
builder.Register(c => app.GetDataProtectionProvider()).InstancePerRequest();
builder.RegisterType<ApplicationUserStore>().As<IUserStore<EverLogicMamber, int>>()
.WithParameter(new TypedParameter(typeof(ISecurityOfWork), new SecurityOfWork(new SecurityDbContext())))
.InstancePerRequest();
//Database
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerRequest();
builder.RegisterType<SecurityOfWork>().As<ISecurityOfWork>().InstancePerRequest();
//Service
builder.RegisterType<TechnicianTimeService>().As<ITechnicianTimeService>().InstancePerRequest();
builder.RegisterType<PartService>().As<IPartService>().InstancePerRequest();
builder.RegisterType<TechServiceItemService>().As<ITechServiceItemService>().InstancePerRequest();
//Repo
builder.RegisterType<Company>().As<ICompany>().InstancePerRequest();
builder.RegisterType<Views>().As<IViews>().InstancePerRequest();
builder.RegisterType<RepairOrderItems>().As<IRepairOrderItems>().InstancePerRequest();
builder.RegisterType<PartInventory>().As<IPartInventory>().InstancePerRequest();
builder.RegisterType<Files>().As<IFiles>().InstancePerRequest();
builder.RegisterType<TechDashboardService>().As<ITechDashboardService>().InstancePerRequest();
builder.RegisterType<RepairOrderUnit>().As<IRepairOrderUnit>().InstancePerRequest();
builder.RegisterType<RepairOrderStatus>().As<IRepairOrderStatus>().InstancePerRequest();
builder.RegisterType<Customer>().As<ICustomer>().InstancePerRequest();
builder.RegisterType<ServiceItem>().As<IServiceItem>().InstancePerRequest();
builder.RegisterType<RepairOrder>().As<IRepairOrder>().InstancePerRequest();
builder.RegisterType<Sproc>().As<ISproc>().InstancePerRequest();
builder.RegisterType<TechServiceItem>().As<ITechServiceItem>().InstancePerRequest();
builder.RegisterType<TechnicianTime>().As<ITechnicianTime>().InstancePerRequest();
// REGISTER CONTROLLERS SO DEPENDENCIES ARE CONSTRUCTOR INJECTED
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterWebApiFilterProvider(config);
builder.RegisterWebApiModelBinderProvider();
var container = builder.Build();
// REPLACE THE MVC DEPENDENCY RESOLVER WITH AUTOFAC
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
app.UseAutofacMiddleware(container);
app.UseAutofacMvc();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
ConfigureAuth(app);
}
但是通过此设置,数据库不会更新或添加新实体。 然后,我尝试从UnitOfWork移除Dependcy注入,并将UnitOfWork设置为
protected DataDbContext _db;
public UnitOfWork(DataDbContext context)
{
GetData();
RepairOrderItems = new RepairOrderItems(_db);
PartInventory = new PartInventory(_db);
Files = new Files(_db);
RepairOrderUnit = new RepairOrderUnit(_db);
RepairOrderStatus = new RepairOrderStatus(_db);
RepairOrder = new RepairOrder(_db);
Customer = new Customer(_db);
Sproc = new Sproc(_db);
ServiceItem = new ServiceItem(_db);
TechServiceItem = new TechServiceItem(_db);
TechnicianTime = new TechnicianTime(_db);
}
internal void GetData()
{
if (_db == null)
{
string accountNumber = HttpContext.Current.User.Identity.GetCompanyAccountNumber();
var connectionToken = ConfigurationManager.AppSettings["LoginSplitToken"];
_db = new DataDbContext(ConfigurationManager.ConnectionStrings["NameOfConnString"].ConnectionString.Replace(connectionToken, accountNumber));
}
}
,然后将SaveChanges从BaseRepo移到UnitOfWork,但是仍然没有任何内容正在保存或添加到数据库中。 我想念什么??
答案 0 :(得分:1)
TL; DR 问题是您所有的存储库都使用单独的独立DbContexts
,因此注入到DbContext
中的UnitOfWork
没有待处理的更改当您在其上调用SaveChanges
时,这就是为什么您看不到数据库的任何更改。
为了使工作单元正常运行,您的UnitOfWork
类以及代码执行数据持久化所需的所有存储库类都必须共享相同的DbContext
实例。在您的代码中,很明显,每个存储库都有一个工厂方法来创建自己的独立DbContext
实例。
GetData()
类中删除BaseRepository
工厂方法,而是要求由AutoFac将EverLogicDbContext
实例的一个实例注入到BaseRepository
的构造函数中。这将要求您所有的存储库子类也需要具有接受相同的EverLogicDbContext
的构造函数。UnitOfWork
类必须接受存储库使用的相同共享EverLogicDbContext
。由于您已经标记了asp.net-mvc
,因此RequestPerInstance
的生存期范围对于您的情况是正确的。UnitOfWork
类需要控制SaveChanges(Async)
方法,因此从CompleteData
类中删除BaseRepository
方法。DbContext
需要注册InstancePerRequest
:
builder.RegisterType<EverLogicDbContext>().AsSelf().InstancePerRequest();
如果所有这些都正确地绑在一起:
DbContext
实例第一次创建。DbContext
实例,并且DbContext将跟踪您的服务所做的临时更改。UnitOfWork
将能够Commit
通过简单地在共享计算机上调用SaveChangesAsync
来执行的操作。 DbContext
。这一切都将在单个数据库连接下发生,因此将是轻量级的事务。根据上面的其他评论,IMO实体框架已经是内置了事务支持的已经很高级的框架,因此,如果所有ACID活动都将针对同一数据库进行,则过度设计“ UnitOfWork”模式毫无意义。 (并且可以包装到同一DbContext中。)