如何将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,事件参数用于传递结果。我很高兴张贴一些工作代码,如果有人感兴趣,只需在评论中留下请求。
我认为你是在正确的轨道上,但在我看来你的解决方案是不正确的,如果你是,事实上,试图解耦你的视图模型从你的数据服务。我现在正在开发一个类似的应用程序。不同的人对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;
} );
}
如果你真的想要解耦,你可以更进一步,为数据服务实现一个接口。采用这种方法允许您的数据服务的可重用性(如果您想要桌面应用程序或手机应用程序),我希望这有助于澄清问题!