我正在尝试在所有存储库之间共享我的DBcontext,
所以这是我的workflowContext
public class WorkflowContext : DbContext {
public WorkflowContext()
: base("name=WorkflowContext") {
}
public DbSet<Instance> Instances { get; set; }
public DbSet<Task> Tasks { get; set; }
}
这是baseRepo
public class WorkFlowBaseRepo {
protected static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
internal WorkflowContext Db;
public WorkFlowBaseRepo() {
Db = new WorkflowContext();
}
internal void SetState(object instance, EntityState state) {
Log.DebugFormat("setting {0} state", ObjectContext.GetObjectType(instance.GetType()));
try {
if (Db.Entry(instance).State != EntityState.Added) {
Db.Entry(instance).State = state;
}
} catch (Exception e) {
Log.Error("Error setting state", e);
}
}
internal int SaveChanges() {
Log.DebugFormat("Saving changes");
try {
return Db.SaveChanges();
} catch (Exception e) {
Log.Error("Error Saving", e);
return -1;
}
}
internal void Dispose() {
try {
Db.Dispose();
} catch (Exception e) {
Log.Error("Error disposing", e);
}
}
}
然后repo继承自WorkflowBaseRepo
,这是一个回购的例子:
public class InstanceRepo : WorkFlowBaseRepo {
private readonly DocumentRepo _documentRepo;
private readonly TaskRepo _taskRepo;
private readonly WorkflowRepo _workflowRepo;
private readonly MailService _mailService;
private readonly QService _qService;
private readonly OService _oService;
public InstanceRepo() {
_workflowRepo = new WorkflowRepo();
_mailService = new MailService();
_documentRepo = new DocumentRepo();
_taskRepo = new TaskRepo();
_oService = new OService();
_qService = new QService();
}
internal List<Instance> GetAll() {
Log.DebugFormat("Getting all Instances");
try {
return Db.Instances.ToList();
} catch (Exception e) {
Log.Error("Error getting all instance", e);
return null;
}
}
internal Instance GetById(int id) {
Log.DebugFormat("Getting instance {0}", id);
try {
var instance = Db.Instances.Find(id);
var docid = instance.Document != null ? instance.Document.Id : -1;
instance.Document = _documentRepo.GetByDocumentId(instance.ObjectId);
if (instance.Document.Id != docid) {
Db.SaveChanges();
}
return instance;
} catch (Exception e) {
Log.Error("Error finding instance", e);
return null;
}
}
internal Instance AddInstance(InstancePostDto instance) {
// code
}
internal Instance RemoveInstance(Instance instance) {
Log.DebugFormat("Removing Instance {0}", instance.Id);
try {
return Db.Instances.Remove(instance);
} catch (Exception e) {
Log.Error("Error removing instance", e);
return null;
}
}
internal void SetState(Instance instance, EntityState state) {
try {
base.SetState(instance, state);
instance.UdatedDate = DateTime.Now;
} catch (Exception e) {
Log.Error("Error", e);
}
}
internal bool InstanceExists(int id) {
try {
return Db.Instances.Count(e => e.Id == id) > 0;
} catch (Exception e) {
Log.Error("Error", e);
return false;
}
}
}
但是现在我在更新The relationship between the two objects cannot be defined because they are attached to different ObjectContext objects.
知道为什么会这样吗?以及如何解决它?
答案 0 :(得分:3)
您没有在您的存储库中共享DbContext
,每个存储库都从基类的构造函数中获取它的新实例:
public WorkFlowBaseRepo() {
Db = new WorkflowContext();
}
这就是为什么您会看到相关对象附加到上下文的不同实例的异常。您的InstanceRepo
实际上有7个WorkflowContext
的不同实例。
解决此问题的最佳方法是使用依赖注入容器(也称为控制容器的反转),如SimpleInjector,StructureMap,Ninject,Autofac,Castle Windsor ......还有其他选择。使用其中一个来启用构造函数注入,然后将DbContext实例注册为作用域依赖项。这样,您将在应用程序中获得其中一个每个作用域操作(例如,在Web应用程序中,&#34;范围&#34;将意味着单个请求)。
像这样(伪代码)
var container = new Container();
container.RegisterScoped<WorkflowContext>(x => new WorkflowContext());
container.Verify();
public class WorkFlowBaseRepo {
internal WorkflowContext Db;
public WorkFlowBaseRepo(WorkflowContext db) {
Db = db;
}
然后,您的容器将确保所有repos在同一范围内收到WorkflowContext
依赖项的相同引用实例。
注意我是如何使DbContext
成为构造函数的参数。如果你真的厌恶IoC,你可能会得到类似的东西:
public InstanceRepo(WorkflowContext db) {
Db = db ?? new WorkflowContext();
_workflowRepo = new WorkflowRepo(Db);
_mailService = new MailService(Db);
_documentRepo = new DocumentRepo(Db);
_taskRepo = new TaskRepo(Db);
_oService = new OService(Db);
_qService = new QService(Db);
}
通过以上操作,您的InstanceRepo
正在与其他所有回购商共享其DbContext
的实例。但请注意,在这里,我们仍然是#34;构造函数注入&#34;一个依赖项,即使没有IoC容器。