public class SqlDataContext : DbContext
{
public DbSet<Message> Messages { get; set; }
protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
和存储库类:
public class SqlRepository : IRepository
{
private SqlDataContext _dataContext;
public SqlRepository(SqlDataContext dataContext) {
_dataContext = dataContext;
}
public DbSet<Message> Messages {
get { return _dataContext.Messages; }
}
public void Commit() {
_dataContext.SaveChanges();
}
}
和服务类:
public class MessagesServices : IMessagesServices
{
#region Repository
private IRepository _repository;
public UsersServices(IRepository repository) {
_repository = repository;
}
#endregion
/// <summary>
/// Update the Message in Repository
/// </summary>
public void Update(Message message) {
if (message != null) {
_repository.Messages.Attach(message);
_repository.Commit();
}
}
}
如果我收到这样的消息:
public ViewResult Edit(int messageId)
{
var message = _repository.Messages.First(j => j.MessageId == messageId);
message.Text = "Test";
_userService.Update(message);
}
一切都会好的,但更改不会保存到数据库中。
消息控制器构造函数
private IRepository _repository;
private IMessagesServices _messageServices;
public MessagesController(IRepository repository, IMessagesServices messageServices)
{
_repository = repository;
_messageServices = messageServices;
}
存储库,服务和数据上下文由结构图注入:
/// <summary>
/// Configuration registry modules for DI
/// </summary>
public class WebUiRegistry : Registry
{
public WebUiRegistry()
{
For<DbContext>().Use(() => new SqlDataContext());
For<IRepository>().HttpContextScoped().Use<SqlRepository>();
For<IUsersServices>().Use<UsersServices>();
For<IMessagesServices>().Use<MessagesServices>();
For<IJobAdvertsServices>().Use<JobAdvertsServices>();
For<ILog>().Use<SqlLogServices>();
}
}
@slauma你没事。
如果我试试这个:
ObjectFactory.GetInstance<SqlDataContext>().Messages.Attach(message);
ObjectFactory.GetInstance<SqlDataContext>().Entry(message).State = EntityState.Modified;
ObjectFactory.GetInstance<SqlDataContext>().SaveChanges();
他们一切正常,所以我有多个SqlDataContext实例。
但是这个:
For<SqlDataContext>().Use(() => new SqlDataContext());
没有帮助。有什么想法吗?
我认为,问题在这里
private IRepository _repository;
private IMessagesServices _messageServices;
public MessagesController(IRepository repository, IMessagesServices messageServices)
{
_repository = repository;
_messageServices = messageServices;
}
因为这里注入了存储库(在存储库中注入了SqlDataContext)并且同时注入了服务(在注入的存储库中,在存储库SqlDataContext中)
public class MessageController : Controller
{
private IRepository _repository;
private IMessagesServices _messagesServices;
public MessageController(IRepository repository, IMessagesServices messagesServices)
{
_repository = repository;
_messagesServices = messagesServices;
bool sameDataContexts = object.ReferenceEquals(((SqlRepository)_repository)._dataContext, ((SqlRepository)((MessagesServices)_messagesServices)._repository)._dataContext);
}
结果为TRUE。
工作解决方案:
private IRepository _repository;
private IMessagesServices _messageServices;
public MessagesController(IRepository repository)
{
_repository = repository;
_messageServices = ObjectFactory.GetInstance<IUsersServices>();
}
并在服务类中:
/// <summary>
/// Update the Message in Repository
/// </summary>
public void Update(Message message) {
if (message != null) {
_repository.Messages.Attach(message);
ObjectFactory.GetInstance<SqlDataContext>().Entry(message).State = EntityState.Modified;
_repository.Commit();
}
但我在这里有两个构造函数参数的解决方案吗?并且不使用
ObjectFactory.GetInstance<SqlDataContext>().Entry(message).State = EntityState.Modified;
答案 0 :(得分:1)
尝试替换此行......
For<DbContext>().Use(() => new SqlDataContext());
...通过
For<SqlDataContext>().Use(() => new SqlDataContext());
(如果您还需要在其他地方解析DbContext
,请添加此行)
您的SqlRepository
想要SqlDataContext
作为构造函数参数,而不是DbContext
。因此,当SqlDataContext
被解析并且IRepository
被解析时,您的DI容器会创建IMessagesServices
的两个新实例,而不是使用已注册的SqlDataContext实例。您的存储库和服务类将使用两个不同的数据上下文,这将导致更新失败。
这只是猜测,我不知道StructureMap的细节。但是使用Unity(我更熟悉),这是行不通的:Unity不会在需要派生类的地方注入已注册基类的实例。您需要注册要注入的确切类类型。
修改强>
检查注入存储库和服务的DataContexts是否真的相同是个好主意,例如在Controller的Edit
方法中:
bool sameDataContexts = object.ReferenceEquals(_repository._dataContext,
_messageServices._repository._dataContext);
(暂时为该测试在服务器类public
中的存储库和_repository中创建_dataContext。)
通过这种方式,我们可以清楚地区分您是否存在注射问题或EF问题。