【问题标题】:How to refactor RIA data service calls to a service layer?如何将 RIA 数据服务调用重构到服务层?
【发布时间】:2011-08-29 17:28:44
【问题描述】:

我在使用 RIA 服务和实体的 Silverlight 4 应用程序中遇到一些基本的 MVVM 设计原则。这是似乎可以正常工作的基本方案:

DataViewModel.cs

public DataViewModel : NotificationObject

    private DataDomainContext _dataContext;

    public DataViewModel()  
    {
       _dataContext = new DataDomainContext();

       if (!DesignerProperties.IsInDesignTool)
       {
         Data = _dataContext.Data;
         dataContext.Load(_dataContext.GetDataQuery(), null, null);
       }
    }

    private IEnumerable<DataEntity> _data;
    public IEnumerable<DataEntity> Data   // INPC property
    {
        get { return _data; }
        set
        {
            if (value != _data)
            {
                _data = value;
                PropertyChanged(this, new PropertyChangedEventArgs("Data"));
            }
        }
    }
}

在我看来,DataGrid 单向绑定到 DataViewModel.Data,DataDomainContext 是在为 DataEntity 对象编译域服务后公开的 RIA 域上下文。

我想将视图模型与 DAL 分离。我想要一个 DataService 类,它会负责向域上下文询问数据:

public DataViewModel : NotificationObject

    private DataService _dataService;

    public DataViewModel(DataService dataService)  
    {
       _dataService = dataService;

       if (!DesignerProperties.IsInDesignTool)
       {
         Data = _dataService.Data;
         _dataService.GetData();
       }
    }

    ...
}

但是,我似乎无法做到这一点。这很容易做到吗?我之前没有设计过带有回调的数据服务。我尝试通过 INPC 跨三个类链接数据属性,但 UI 中的 DataGrid 出现空白。我还想转换为新类型 DataDto 的集合,因此我的表示层不与后端耦合。我没有运气就尝试过这样的事情:

DataService.cs

public DataService : INotifyPropertyChanged
{
   public DataService()
   {
     _dataContext = new DataDomainContext();
   }

   public event PropertyChangedEventHandler PropertyChanged;

   public void GetData()
   {
     DataEntities = _domainContext.Data;
     _dataContext.Load(_dataContext.GetDataQuery(), FinishedLoading, null);
   }

   private void FinishedLoading(...)
   {
      Data = DataEntities.Select(de => new DataDto(de));
   }

   public IEnumerable<DataDto> Data { ... }  // INPC property, used for binding in ViewModel

   public IEnumerable<DataEntity> DataEntities { ... }  // INPC property

   ...
}

我在这里走对了吗?我是否遗漏了任何高层次的东西,或者我只是没有正确的细节?

编辑:

我最终能够弄清楚这一点。答案涉及通过 Action 将回调传递给数据服务/存储库调用。调用的返回类型实际上是 void,并且使用事件参数来传递结果。如果有人感兴趣,我很乐意发布一些工作代码,只需在 cmets 中留下请求即可。

【问题讨论】:

  • 嗨,克里斯,您应该继续发布结果,它将帮助将来找到此结果的人。如您所见,在 Silverlight 中按要求异步完成时,数据服务层完全不同。听起来您找到了正确的解决方案:-)

标签: c# silverlight entity-framework mvvm ria


【解决方案1】:

我认为您走在正确的轨道上,但在我看来如果您实际上试图将视图模型与数据服务分离,那么您的解决方案是不正确的。我现在正在开发一个与此非常相似的应用程序。不同的人对 mvvm 有不同的想法,这只是我从反复试验中学到的个人方法(使用 Visual Studio):

首先创建 silverlight 应用程序项目并将其托管在 .web 项目中。 silverlight 项目将保存视图和视图模型。视图模型应该包含您的模型,而不是您的数据服务!但是,视图模型应该有一个数据服务实例来设置模型。我的数据服务在哪里?我很高兴你问:)。添加另一个项目,一个 WCF RIA 服务类库。这实际上是两个项目,一个 ria 服务(服务器端)dll 和一个相应的 silverlight(客户端)dll。您可以将实体框架或其他数据库访问代码添加到服务器端。之后,将域服务添加到服务器端项目。首先构建它(重要),然后转到客户端 ria 服务 dll 并使用您的数据服务方法创建一个数据服务类,如下所示:

public void GetData( string filter, Action<LoadOperation<MyEntityType>> callback )
    {
        var q = from e in _context.GetDataQuery()
                where e.SomeField.Contains(filter)
                select e;
        _context.Load(q, LoadBehavior.RefreshCurrent, callback, null);
    }

您的数据服务不应实施 Inotifyproperty 更改,因为那是视图模型角色! 在您的 silverlight 项目中引用 ria 服务客户端 dll,并在您的 Web 主机项目中引用 ria 服务服务器端 dll 视图模型应该像这样调用这个数据服务:

IEnumerable<MyEnityType> Model {get;set;}
//NOTE: add notify property changed in setter!

private void GetData()
{
    _myDataService.GetData( _filter, loadOperation =>
            {
                if ( loadOperation.HasError )
                    HandleError(loadOperation.Error);    
                Model = loadOperation.Entities;
            } );
}

如果你真的想解耦它们,你可以更进一步,为数据服务实现一个接口。采用这种方法可以重用您的数据服务(如果您需要桌面应用程序或手机应用程序)我希望这有助于解决问题!

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-29
  • 1970-01-01
  • 2011-04-22
  • 2011-07-14
  • 2012-01-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多