Asp.net mvc 具有实体框架和更新记录的MVC存储库模式

Asp.net mvc 具有实体框架和更新记录的MVC存储库模式,asp.net-mvc,entity-framework,dependency-injection,repository-pattern,Asp.net Mvc,Entity Framework,Dependency Injection,Repository Pattern,我试图在MVC应用程序中使用EntityFramework的repository模式来更新记录,但是db.SaveChanges()方法没有保存到数据库中。我没有收到任何错误,我可以逐步检查代码,看到传递了正确的变量,以及更新了记录变量 根据我所阅读的内容,我认为我的问题在于我有两个数据库上下文实例(MyDBEntities)。问题可能是,创建MyDBEntities实例的my ReadRepository被注入到WriteRepository中,而WriteRepository也创建了一个实例

我试图在MVC应用程序中使用EntityFramework的repository模式来更新记录,但是db.SaveChanges()方法没有保存到数据库中。我没有收到任何错误,我可以逐步检查代码,看到传递了正确的变量,以及更新了记录变量

根据我所阅读的内容,我认为我的问题在于我有两个数据库上下文实例(MyDBEntities)。问题可能是,创建MyDBEntities实例的my ReadRepository被注入到WriteRepository中,而WriteRepository也创建了一个实例MyDBEntities。我不确定如何将实体注入到存储库中(假设我需要这样做)

如果我尝试添加类似于
db.MyTable.Attach(记录)的内容
db.SaveChanges()
之前,我将在下面得到这个错误,这使我认为我需要注入
MyDBEntities()

一个实体对象不能被多个IEntityChangeTracker实例引用。

控制器

public class MyController : Controller
{
    private IWriteRepository _writeRepository;

    public MyController(IWriteRepository writeRepository)
    {
        _writeRepository = writeRepository;
    }

    [HttpPost]
    public ActionResult MyPostMethod(MyViewModel model)
    {
        try
        {
            //Send to the repository to edit a record
            writeRepository.EditRecord(model);

            return new HttpStatusCodeResult(HttpStatusCode.OK);
        }
        catch
        {
            throw new HttpException(500, "Internal Server Error");
        }            
    }
}
写入存储库

//The ReadRepository is injected into the WriteRepository to grab records from the database
public class WriteRepository : IWriteRepository
{
    private MyDBEntities db = new MyDBEntities();
    private IReadRepository _readRepository;

    public WriteRepository(IReadRepository readeadRepository)
    {
        _readRepository = readRepository;
    }        

    public void EditRecord(MyViewModel model)
    {
        //Get the specific record to be updated
        var record = readRepository.GetRecord(model.ID);

        //Update the data
        record.FirstName = model.Name;

        //This isn't saving
        db.SaveChanges();
    }
}
public class ReadRepository : IReadRepository
{
    private MyDBEntities db = new MyDBEntities();

    //Provides the record to the write repository to edit
    public MyTable GetRecord(int ID)
    {
        var record = (from t in db.MyTable
                      where t.ID == ID
                      select t).SingleOrDefault();

        return record;
    }
}
读取存储库

//The ReadRepository is injected into the WriteRepository to grab records from the database
public class WriteRepository : IWriteRepository
{
    private MyDBEntities db = new MyDBEntities();
    private IReadRepository _readRepository;

    public WriteRepository(IReadRepository readeadRepository)
    {
        _readRepository = readRepository;
    }        

    public void EditRecord(MyViewModel model)
    {
        //Get the specific record to be updated
        var record = readRepository.GetRecord(model.ID);

        //Update the data
        record.FirstName = model.Name;

        //This isn't saving
        db.SaveChanges();
    }
}
public class ReadRepository : IReadRepository
{
    private MyDBEntities db = new MyDBEntities();

    //Provides the record to the write repository to edit
    public MyTable GetRecord(int ID)
    {
        var record = (from t in db.MyTable
                      where t.ID == ID
                      select t).SingleOrDefault();

        return record;
    }
}

从您的MyController代码来看,您似乎已经在使用控制反转框架,因此请按如下方式更新您的ReadRepositoryWriteRepository类:

ReadRepository

public class ReadRepository : IReadRepository
{
    private MyDBEntities db;

    public ReadRepository(MyDBEntities myDbEntities) 
    {
        db = myDbEntities;
    }

    //Provides the record to the write repository to edit
    public MyTable GetRecord(int ID)
    {
        var record = (from t in db.MyTable
                      where t.ID == ID
                      select t).SingleOrDefault();

        return record;
    }
}
public class WriteRepository : IWriteRepository
{
    private MyDBEntities db;
    private IReadRepository _readRepository;

    public WriteRepository(MyDBEntities myDbEntities, IReadRepository readeadRepository)
    {
        db = myDbEntities;
        _readRepository = readRepository;
    }        

    public void EditRecord(MyViewModel model)
    {
        //Get the specific record to be updated
        var record = readRepository.GetRecord(model.ID);

        //Update the data
        record.FirstName = model.Name;

        //This isn't saving
        db.SaveChanges();
    }
}
WriteRepository

public class ReadRepository : IReadRepository
{
    private MyDBEntities db;

    public ReadRepository(MyDBEntities myDbEntities) 
    {
        db = myDbEntities;
    }

    //Provides the record to the write repository to edit
    public MyTable GetRecord(int ID)
    {
        var record = (from t in db.MyTable
                      where t.ID == ID
                      select t).SingleOrDefault();

        return record;
    }
}
public class WriteRepository : IWriteRepository
{
    private MyDBEntities db;
    private IReadRepository _readRepository;

    public WriteRepository(MyDBEntities myDbEntities, IReadRepository readeadRepository)
    {
        db = myDbEntities;
        _readRepository = readRepository;
    }        

    public void EditRecord(MyViewModel model)
    {
        //Get the specific record to be updated
        var record = readRepository.GetRecord(model.ID);

        //Update the data
        record.FirstName = model.Name;

        //This isn't saving
        db.SaveChanges();
    }
}
您的ReadRepositoryWriteRepository都依赖于MyDBEntities的实例来执行工作,因此,您应该在这些类的构造函数中指定该依赖项,并让您的控制反转框架来处理创建它,而不是自己创建一个新的MyDBEntities实例

确保在控制反转框架的注册中,您正在将您的MyDBEntities实例注册为作用域或每个请求,而不是临时的。您希望确保在每次请求时,您的ReadRepositoryWriteRepository都会被注入与MyDBEntities类相同的实例,而不是像现在这样的两个独立实例

按如下方式更新Unity配置:

UnityConfig.cs

在每个请求范围内向Unity注册您的MyDBEntities

public class UnityConfig
{
    // ... other methods ...

    public static void RegisterTypes(IUnityContainer container)
    {
        // ... other registrations ...
        container.RegisterType<IReadRepository, ReadRepository>();
        container.RegisterType<IWriteRepository, WriteRepository>();
        container.RegisterType<MyDBEntities>(new PerRequestLifetimeManager());
        // ... other registrations ...
    }
}

从您的MyController代码来看,您似乎已经在使用控制反转框架,因此请按如下方式更新您的ReadRepositoryWriteRepository类:

ReadRepository

public class ReadRepository : IReadRepository
{
    private MyDBEntities db;

    public ReadRepository(MyDBEntities myDbEntities) 
    {
        db = myDbEntities;
    }

    //Provides the record to the write repository to edit
    public MyTable GetRecord(int ID)
    {
        var record = (from t in db.MyTable
                      where t.ID == ID
                      select t).SingleOrDefault();

        return record;
    }
}
public class WriteRepository : IWriteRepository
{
    private MyDBEntities db;
    private IReadRepository _readRepository;

    public WriteRepository(MyDBEntities myDbEntities, IReadRepository readeadRepository)
    {
        db = myDbEntities;
        _readRepository = readRepository;
    }        

    public void EditRecord(MyViewModel model)
    {
        //Get the specific record to be updated
        var record = readRepository.GetRecord(model.ID);

        //Update the data
        record.FirstName = model.Name;

        //This isn't saving
        db.SaveChanges();
    }
}
WriteRepository

public class ReadRepository : IReadRepository
{
    private MyDBEntities db;

    public ReadRepository(MyDBEntities myDbEntities) 
    {
        db = myDbEntities;
    }

    //Provides the record to the write repository to edit
    public MyTable GetRecord(int ID)
    {
        var record = (from t in db.MyTable
                      where t.ID == ID
                      select t).SingleOrDefault();

        return record;
    }
}
public class WriteRepository : IWriteRepository
{
    private MyDBEntities db;
    private IReadRepository _readRepository;

    public WriteRepository(MyDBEntities myDbEntities, IReadRepository readeadRepository)
    {
        db = myDbEntities;
        _readRepository = readRepository;
    }        

    public void EditRecord(MyViewModel model)
    {
        //Get the specific record to be updated
        var record = readRepository.GetRecord(model.ID);

        //Update the data
        record.FirstName = model.Name;

        //This isn't saving
        db.SaveChanges();
    }
}
您的ReadRepositoryWriteRepository都依赖于MyDBEntities的实例来执行工作,因此,您应该在这些类的构造函数中指定该依赖项,并让您的控制反转框架来处理创建它,而不是自己创建一个新的MyDBEntities实例

确保在控制反转框架的注册中,您正在将您的MyDBEntities实例注册为作用域或每个请求,而不是临时的。您希望确保在每次请求时,您的ReadRepositoryWriteRepository都会被注入与MyDBEntities类相同的实例,而不是像现在这样的两个独立实例

按如下方式更新Unity配置:

UnityConfig.cs

在每个请求范围内向Unity注册您的MyDBEntities

public class UnityConfig
{
    // ... other methods ...

    public static void RegisterTypes(IUnityContainer container)
    {
        // ... other registrations ...
        container.RegisterType<IReadRepository, ReadRepository>();
        container.RegisterType<IWriteRepository, WriteRepository>();
        container.RegisterType<MyDBEntities>(new PerRequestLifetimeManager());
        // ... other registrations ...
    }
}

可能是我读过的那一部分的重复,但是我正在寻找关于如何在存储库之外创建数据库上下文的帮助。可能是我读过的那一部分的重复,但是我正在寻找关于如何在存储库之外创建数据库上下文的帮助。回答很好。你正按照我的要求行事。实际上,我在使用Unity作为框架,但在最后一部分中,我不知道注册什么或如何注册实体。好的,我用Unity注册更新了我的答案。谢谢更新。如果一切正常,我会试试这个,并把它作为答案。我们能得到一些反馈吗,@madvora?请标记为已回答或添加其他后续评论。僵尸问题伤害了所有人。回答得很好。你正按照我的要求行事。实际上,我在使用Unity作为框架,但在最后一部分中,我不知道注册什么或如何注册实体。好的,我用Unity注册更新了我的答案。谢谢更新。如果一切正常,我会试试这个,并把它作为答案。我们能得到一些反馈吗,@madvora?请标记为已回答或添加其他后续评论。僵尸问题伤害了所有人。