如何将RIA数据服务调用重构到服务层

本文关键字:服务 调用 重构 数据 RIA | 更新日期: 2023-09-27 18:06:52

我在使用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。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,事件参数用于传递结果。我很高兴张贴一些工作代码,如果有人感兴趣,只需在评论中留下请求。

如何将RIA数据服务调用重构到服务层

我认为你是在正确的轨道上,但在我看来你的解决方案是不正确的,如果你是,事实上,试图解耦你的视图模型从你的数据服务。我现在正在开发一个类似的应用程序。不同的人对mvvm有不同的想法,这只是我个人的方法,我从试验和错误(使用visual studio)中学到的:

首先创建silverlight应用程序项目并将其托管在.web项目中。silverlight项目将保存视图和视图模型。视图模型应该包含你的模型,而不是数据服务!但是,视图模型应该有一个数据服务的实例来设置模型。我的数据服务在哪里?很高兴你这么问。添加另一个项目,一个WCF RIA服务类库。这实际上是两个项目,一个ria service(服务器端)dll和一个相应的silverlight(客户端)dll。您可以将实体框架或其他数据库访问代码添加到服务器端。之后,向服务器端项目添加域服务。首先构建它(很重要),然后通过service 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 changed,因为那是视图模型的角色!在你的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;
            } );
}

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