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

时间:2011-08-29 17:28:45

标签: c# silverlight entity-framework mvvm ria

我正在使用RIA服务&amp ;;在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&lt;&gt;将回调传递给数据服务/存储库调用。调用的返回类型实际上是无效的,事件args用于传递结果。如果有人有兴趣,我很乐意发布一些有效的代码,只需在评论中留下请求。

1 个答案:

答案 0 :(得分:2)

我认为你走在正确的轨道上,但在我看来你的解决方案是不正确的,如果你实际上试图将你的视图模型与数据服务分离。我正在开发一个与此非常相似的应用程序。不同的人对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;
            } );
}

如果您真的想要解耦数据服务,可以更进一步,实现数据服务的接口。采用这种方法可以重新使用您的数据服务(如果您需要桌面应用程序或手机应用程序),我希望这有助于清理事情!