DomainContext从客户端项目内部,我们不直接与域服务交互。相反,会对服务端中的每个域服务在客户端生成一个域上下文类。我们在域上下文类上调用对应于域服务上想使用的方法。这个生成的域上下文类派生于DomainContext类。
查询
域上下文中的查询方法通常与域服务中的查询方法有相同的名字,并有后缀Query。例如,一个域上下文中的GetCustomersQuery方法生成于域服务中的GetCustomers方法。这个查询方法返回一个EntityQuery对象,我们可以在其他操作中应用这个对象。
域上下文中的所有查询方法都是异步执行的。为了执行这个查询,我们在Load方法中把EntityQuery对象作为参数传递。


//查询的第一种写法:
            this.CustomerGrid.ItemsSource = _customerDomainContext.Customers;
            _customerDomainContext.Load(_customerDomainContext.GetCustomersByIDQuery(IDValue.Text));
            
            //查询的第二种写法:
            LoadOperation<Customers> loadOp = this._customerDomainContext.Load(
                this._customerDomainContext.GetCustomersByIDQuery(IDValue.Text)
                );
            CustomerGrid.ItemsSource = loadOp.Entities;

修改数据
当域服务中包含更新、插入、删除实体的方法时,在域上下文中不会生成这些方法。反之,我们在与上下文中使用SubmitChanges方法,会调用域服务中的正确操作。直到我们调用SubmitChanges时,才会在数据源中进行更改。可以通过调用RejectChanges方法来取消更改。
DomainContext类还提供HasChanges和EntityContainer属性来允许我们评估行将发生的更改。对Domain context的EntityContainer对象跟踪行将发生的更改。行将发生的更改不包括对域服务中的操作的调用,因为这些操作会在被调用时立即执行。当调用SubmitChanges时,所有的行将发生的更改都一起发到域服务。

例子:在xalm页面上设置一个datagrid,当查询完数据在datagrid显示后,直接在datagrid上修改后,点击SubmtChange按钮后,把修改的数据update到数据库端:

private void SubmitChange_Click(object sender, RoutedEventArgs e)
        {
            _customerDomainContext.SubmitChanges();
        }

增加一行新数据,需要new一个新的对象,然后赋值后SubmitChanges(本例为新增加一个ChildWindow Popup新窗口):

private void OKButton_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = true;
            Customers customer = new Customers();
            customer.CustomerID = this.CustomerID.Text;
            customer.CompanyName = this.CompanyName.Text;
            
            CustomerDomainContext _customerDomainContext = new CustomerDomainContext();
            _customerDomainContext.Customers.Add(customer);
            _customerDomainContext.SubmitChanges();
            
        }

删除所选一行数据:

//删除所选的Customer
        private void DeleteCustomer_Click(object sender, RoutedEventArgs e)
        {
            Customers customer = new Customers();
            customer = (Customers)this.CustomerGrid.SelectedItem;
            _customerDomainContext.Customers.Remove(customer);
            _customerDomainContext.SubmitChanges();
        }

定制方法
对域服务中的那些有公共访问修饰符而且没有标记着IgnoreOperationAttribute属性的自定义方法,域上下文都会包含这些方法。域上下文中的这些方法的名字与域服务中的方法名字一样。在客户端,我们调用一个方法,直到SubmitChanges被调用时,这个方法才会被实际执行。EntityContainer会将所有对自定义方法的调用作为行将发生的更改来跟踪。当调用SubmitChanges时,方法是异步处理的。
在客户端项目中对实体也会生成同样的自定义方法,这些实体在自定义方法中做为参数传递。因此,可以通过一个域上下文的实例或实体的实例来调用定制的方法。如果打开生成的代码文件,会注意到域上下文中生成的方法只是简单的调用实体内的生成方法。在这两种情况下,我们还是需要调用Submitchanges方法来执行这些方法。
下面的示例演示如何调用一个名为ResetPassword的自定义方法,OnSubmitCompleted是我们想实施处理数据操作结果的回调函数。


?


selectedCustomer.ResetPassword();        


customerContext.SubmitChanges(OnSubmitCompleted,null);


Invoke Operations 调用操作
对域服务上的每个服务操作,域上下文都包含一个方法。与域操作不同,服务操作都会立即执行。不用调用SubmitChanges方法,服务操作会异步执行。服务操作返回一个InvokeOperation对象。我们检索Value属性的值来得到从服务操作中返回的结果。
下面的示例演示了如果调用一个名为GetLocalTemperature的服务操作。


?


InvokeOperation<INT> invokeOp = customerContext.GetLocalTemperature(selectedPostalCode, OnInvokeCompleted,null);
         private         void         OnInvokeCompleted(InvokeOperation<INT> invOp)        
         {        

if         (invOp.HasError)        


{
MessageBox.Show(string.Format("Method Failed: {0}", invOp.Error.Message));
invOp.MarkErrorAsHandled();
}
else
{
result = invokeOp.Value;
}
         }


//使用Invoke来调用DomainContext上指向DomainService的方法
        private void InvokeCustomer_Click(object sender, RoutedEventArgs e)
        {            
            //返回值为string类型的Invoke方法 = DomainContext的GetContractName方法,这个方法其实只有一个参数,但这里为什么还有加上OnInvokeCompleted和null?
            //其实是这样虽然DomainService上的方法只是写了一个参数,但是会在生成DomainContext的时候,自动添加
            //委托类型的参数public InvokeOperation<string> GetContactName(string customerID, Action<InvokeOperation<string>> callback, object userState)
            //可以看出来第二个参数是Action委托类型,这样该方法就会委托给此方法来进行处理,也就是callback返回。
            InvokeOperation<string> invokeOp = _customerDomainContext.GetContactName(((Customers)this.CustomerGrid.SelectedItem).CustomerID, OnInvokeCompleted, null);
        }
        private void OnInvokeCompleted(InvokeOperation<string> invOp)
        {
            if (invOp.HasError)
            {
                MessageBox.Show(string.Format("Method Failed:{0}", invOp.Error.Message));
                invOp.MarkErrorAsHandled();
            }
            else
            {
                MessageBox.Show(invOp.Value);
            }
        }

处理错误
当我们检索或修改数据时,我们必须决定如果处理在这些操作中可能出现的错误。当我们在域上下文上调用检索或修改数据的方法时,我们包含了指定处理错误的步骤的参数。当装载数据时,我们可以指定忽略错误。但在修改数据时,我们必须处理返回的异常。