使用 StructureMap、存储库模式和 UoW 在 MVC 应用程序中通过 LINQtoSQL 进行更新时出现问题

发布于 2024-09-18 22:25:50 字数 3083 浏览 5 评论 0原文

我有一个 ASP MVC 应用程序,使用 LINQ to SQL 进行数据访问。 我正在尝试使用存储库和工作单元模式,其中服务层使用存储库和工作单元。 我在尝试对特定存储库执行更新时遇到问题。

我的应用程序架构如下:

我的服务类:

public class MyService
{
   private IRepositoryA _RepositoryA;
   private IRepositoryB _RepositoryB;
   private IUnitOfWork _unitOfWork;

   public MyService(IRepositoryA ARepositoryA, IRepositoryB ARepositoryB, IUnitOfWork AUnitOfWork)
   {
      _unitOfWork = AUnitOfWork;
      _RepositoryA = ARepositoryA;
      _RepositoryB = ARepositoryB;
   }

   public PerformActionOnObject(Guid AID)
   {
      MyObject obj = _RepositoryA.GetRecords()
                                 .WithID(AID);
      obj.SomeProperty = "Changed to new value";
      _RepositoryA.UpdateRecord(obj);  
      _unitOfWork.Save();
   }
}

存储库接口:

public interface IRepositoryA
{ 
   IQueryable<MyObject> GetRecords();
   UpdateRecord(MyObject obj);
}

存储库 LINQtoSQL 实现:

public class LINQtoSQLRepositoryA : IRepositoryA
{
    private MyDataContext _DBContext;

    public LINQtoSQLRepositoryA(IUnitOfWork AUnitOfWork)        
    {
        _DBConext = AUnitOfWork as MyDataContext;           
    }

    public IQueryable<MyObject> GetRecords()
    {             
        return from records in _DBContext.MyTable                   
               select new MyObject
               {
                  ID = records.ID,
                  SomeProperty = records.SomeProperty
               }
    }


    public bool UpdateRecord(MyObject AObj)
    {
        MyTableRecord record = (from u in _DB.MyTable
                    where u.ID == AObj.ID
                    select u).SingleOrDefault();

        if (record == null)
        {
            return false;
        }           

        record.SomeProperty = AObj.SomePropery;
        return true;
    }
 }

工作单元接口:

public interface IUnitOfWork
{  
    void Save();
}

在数据上下文扩展中实现的工作单元。

public partial class MyDataContext : DataContext, IUnitOfWork
{
   public void Save()
   {
      SubmitChanges();
   }
}

StructureMap 注册表:

 public class DataServiceRegistry : Registry
    {
        public DataServiceRegistry()
        {            
            // Unit of work
            For<IUnitOfWork>()               
                .HttpContextScoped()                
                .TheDefault.Is.ConstructedBy(() => new MyDataContext());

            // RepositoryA
            For<IRepositoryA>()
                .Singleton()
                .Use<LINQtoSQLRepositoryA>();    

            // RepositoryB
            For<IRepositoryB>()
                .Singleton()
                .Use<LINQtoSQLRepositoryB>();    
         }
     }

我的问题是,当我在服务对象上调用 PerformActionOnObject 时,更新不会触发任何 SQL。我认为这是因为 UnitofWork 对象中的数据上下文与数据更改的 RepositoryA 中的数据上下文不同。因此,当服务在其 IUnitOfWork 上调用 Save() 时,底层数据上下文没有任何更新的数据,因此不会触发更新 SQL。

我在 StrutureMap 注册表设置中是否做错了什么?还是设计存在更根本的问题?

非常感谢。

I have an ASP MVC application using LINQ to SQL for data access.
I am trying to use the Repository and Unit of Work patterns, with a service layer consuming the repositories and unit of work.
I am experiencing a problem when attempting to perform updates on a particular repository.

My application architecture is as follows:

My service class:

public class MyService
{
   private IRepositoryA _RepositoryA;
   private IRepositoryB _RepositoryB;
   private IUnitOfWork _unitOfWork;

   public MyService(IRepositoryA ARepositoryA, IRepositoryB ARepositoryB, IUnitOfWork AUnitOfWork)
   {
      _unitOfWork = AUnitOfWork;
      _RepositoryA = ARepositoryA;
      _RepositoryB = ARepositoryB;
   }

   public PerformActionOnObject(Guid AID)
   {
      MyObject obj = _RepositoryA.GetRecords()
                                 .WithID(AID);
      obj.SomeProperty = "Changed to new value";
      _RepositoryA.UpdateRecord(obj);  
      _unitOfWork.Save();
   }
}

Repository interface:

public interface IRepositoryA
{ 
   IQueryable<MyObject> GetRecords();
   UpdateRecord(MyObject obj);
}

Repository LINQtoSQL implementation:

public class LINQtoSQLRepositoryA : IRepositoryA
{
    private MyDataContext _DBContext;

    public LINQtoSQLRepositoryA(IUnitOfWork AUnitOfWork)        
    {
        _DBConext = AUnitOfWork as MyDataContext;           
    }

    public IQueryable<MyObject> GetRecords()
    {             
        return from records in _DBContext.MyTable                   
               select new MyObject
               {
                  ID = records.ID,
                  SomeProperty = records.SomeProperty
               }
    }


    public bool UpdateRecord(MyObject AObj)
    {
        MyTableRecord record = (from u in _DB.MyTable
                    where u.ID == AObj.ID
                    select u).SingleOrDefault();

        if (record == null)
        {
            return false;
        }           

        record.SomeProperty = AObj.SomePropery;
        return true;
    }
 }

Unit of work interface:

public interface IUnitOfWork
{  
    void Save();
}

Unit of work implemented in data context extension.

public partial class MyDataContext : DataContext, IUnitOfWork
{
   public void Save()
   {
      SubmitChanges();
   }
}

StructureMap registry:

 public class DataServiceRegistry : Registry
    {
        public DataServiceRegistry()
        {            
            // Unit of work
            For<IUnitOfWork>()               
                .HttpContextScoped()                
                .TheDefault.Is.ConstructedBy(() => new MyDataContext());

            // RepositoryA
            For<IRepositoryA>()
                .Singleton()
                .Use<LINQtoSQLRepositoryA>();    

            // RepositoryB
            For<IRepositoryB>()
                .Singleton()
                .Use<LINQtoSQLRepositoryB>();    
         }
     }

My problem is that when I call PerformActionOnObject on my service object, the update never fires any SQL. I think this is because the datacontext in the UnitofWork object is different to the one in RepositoryA where the data is changed. So when the service calls Save() on it's IUnitOfWork, the underlying datacontext does not have any updated data so no update SQL is fired.

Is there something I've done wrong in the StrutureMap registry setup? Or is there a more fundamental problem with the design?

Many thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

极度宠爱 2024-09-25 22:25:50

如果某些东西具有作用域依赖项,那么将其注册为单例通常不是一个好主意。正如您所说,他们很可能保留着 IUnitOfWork 的旧实例。

您的存储库是单例的有什么特殊原因吗?我建议也将它们设置为 HttpContext 范围,这样它们就会同步。

It's generally not a good idea to have something registered as singleton if it has scoped dependencies. Most likely they are holding onto old instances of IUnitOfWork, like you said.

Any particular reason your repositories are singleton? I would suggest making them HttpContext scoped as well, that way they will be in sync.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文