异步从ViewModel调用DAL

时间:2013-06-22 11:23:00

标签: wpf architecture mvvm-light data-access-layer

我正在使用MVVM-light构建复合WPF应用程序。我有使用MEF将ViewModel注入其中的视图:

DataContext = App.Container.GetExportedValue<ViewModelBase>(
                ViewModelTypes.ContactsPickerViewModel);

此外,我为每个View(Screens和UserControls)都有ViewModel,其中构造函数通常如下所示:

private readonly ICouchDataModel _couchModel;

    [ImportingConstructor]
    public ContactsPickerControlViewModel(ICouchDataModel couchModel)
    {
        _couchModel = couchModel;
        _couchModel.GetContactsListCompleted+=GetContactsListCompleted;
        _couchModel.GetConcatcsListAsync("Andy");
    } 

目前,我遇到了一些性能问题。一切都很慢。 我有两种相关的问题

  1. 异步调用DAL方法的正确方法是什么(访问我的couchdb)?等待/异步?任务?因为目前我必须围绕每个操作编写很多包装器(OnBegin,OnCompletion),所以我有GetAsyncResult方法,它使用ThreadPool.QueueUserWorkItem,Action等做一些疯狂的事情。 我希望有更优雅的方式来致电

  2. 目前,我的应用程序和每个屏幕上都有一些屏幕,有不同的自定义UserControl,其中一些需要来自DB的相同数据(或略有变化)。 问题:在它们之间共享数据源的正确方法是什么?我主要是查看数据,而不是编辑。

    示例:屏幕A:我有联系人下拉列表用户控件(UC1),以及联系人详细信息用户控件(UC2)。在每个用户控件中,他们的ViewModel正在调用DAL:

    _couchModel.GetConcatcsListAsync( “安迪”);

  3. 完成后,我将结果数据分配给一个属性:

    List<ContactInfo> ContactsList = e.Resuls; 
    

    ContactsList绑定到UC1中DropDownListBox的ItemsSource。同样的故事发生在UC2中。所以我最终得到了两个完全相同的DB调用。 此外,如果我去屏幕B,我有UC1,我将再次拨打DB,当我从屏幕A转到屏幕B时。

    进行这些互动的正确方法是什么?,例如获取数据并将其绑定到UC。

    谢谢。

1 个答案:

答案 0 :(得分:1)

<强> Ad.1
我认为您可以简单地使用Task.Factory异步调用代码(因为您可以摆脱OnBegin,OnCompletion)或者如果您需要更多的灵活性,那么您可以使方法异步。

广告。 2
我认为这样做的好方法是创建DatabaseService(singleton),它将被注入构造函数中。在DatabaseService中,您可以实现一些逻辑来确定是要刷新集合(调用DAL)还是返回相同的(它将是某种缓存)。

然后您可以直接调用DatabaseService而不是DAL,DatabaseService将决定如何处理此调用(从DB获取集合或返回相同或稍微修改过的当前集合)。


修改:
DatabaseService将简单地在ViewModels之间共享一组对象 也许名称“DBCacheService”更合适(您可能只将它用于特殊任务作为缓存集合)。

我不了解您的架构,但基本上您可以将该服务放在您的客户端应用程序中,因此计划将是:

  1. 创建DatabaseService.cs

    [Export(typeof(IDatabaseService))]
    public class DatabaseService : IDatabaseService
    {
        private List<object> _contacts = new List<object>();
    
        public async Task<List<object>> GetConcatcsList(string name)
        {
            if (_contacts.Count == 0)
            {
                //call DAL to get it
                //_contacts = await Task.Factory.StartNew(() => dal.GetContactsList(name));
            }
            else
            {
                //refresh list if required (there could be some condition)                
            }
    
            return _contacts;
        }
    }
    
  2. 将IDatabaseService添加到ViewModel的构造函数中。

  3. 调用IDatabaseService而不是DAL。
  4. 如果选择DatabaseService的异步版本,则需要使用等待并将方法更改为异步。您也可以同步执行并调用它(只要您希望它是异步的):

    Task.Factory.StartNew(() => 
    {
        var result = dbService.GetContactsList("Andy");
    });
    

    <强> EDIT2:

    在Task:

    中调用awaitable方法
    Task.Factory.StartNew(async () => 
    {
        ListOfContacts = await _CouchModel.GetConatcsList ("Andy");
    });