2014-09-05 31 views
3

我在其中包含導航屬性Roads服務端一個Place data_object:Azure的移動服務Lookupasync載導航性能

public class Place : EntityData 
{ 
    ... 
    public List<Road> Roads { get; set; } 
} 

現在在客戶端,我想用它的ID來獲得Place對象,但導航屬性Roads只是不會加載。是否有任何參數或屬性可以添加到使其工作?

我爲它的代碼:在EF

var roadList = await App.MobileService.GetTable<Place>() 
       .LookupAsync(placeId); 

回答

5

由於裝載的導航性能,需要在數據庫中JOIN操作(這是昂貴的),默認情況下它們不會被加載,因爲你注意到了。如果您希望加載它們,則需要通過發送$expand=<propertyName>查詢字符串參數向客戶端請求。

有兩種實現方法:在服務器和客戶端。如果你想在服務器中這樣做,你可以實現一個動作過濾器,它將修改客戶端請求並添加該查詢字符串參數。你可以通過使用下面的過濾器:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] 
class ExpandPropertyAttribute : ActionFilterAttribute 
{ 
    string propertyName; 

    public ExpandPropertyAttribute(string propertyName) 
    { 
     this.propertyName = propertyName; 
    } 

    public override void OnActionExecuting(HttpActionContext actionContext) 
    { 
     base.OnActionExecuting(actionContext); 
     var uriBuilder = new UriBuilder(actionContext.Request.RequestUri); 
     var queryParams = uriBuilder.Query.TrimStart('?').Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries).ToList(); 
     int expandIndex = -1; 
     for (var i = 0; i < queryParams.Count; i++) 
     { 
      if (queryParams[i].StartsWith("$expand", StringComparison.Ordinal)) 
      { 
       expandIndex = i; 
       break; 
      } 
     } 

     if (expandIndex < 0) 
     { 
      queryParams.Add("$expand=" + this.propertyName); 
     } 
     else 
     { 
      queryParams[expandIndex] = queryParams[expandIndex] + "," + propertyName; 
     } 

     uriBuilder.Query = string.Join("&", queryParams); 
     actionContext.Request.RequestUri = uriBuilder.Uri; 
    } 
} 

然後你可以用屬性修飾你的方法:

[ExpandProperty("Roads")] 
public SingleItem<Place> GetPlace(string id) { 
    return base.Lookup(id); 
} 

另一種方式來實現,這是改變客戶端代碼發送該標題。目前,帶有附加查詢字符串參數的LookupAsync(以及所有其他CRUD操作)的重載不能用於添加$expand參數(或任何其他​​參數),因此您需要使用該處理程序。例如,這是一個這樣的處理程序:

class MyExpandPropertyHandler : DelegatingHandler 
{ 
    string tableName 
    string propertyName; 

    public MyExpandPropertyHandler(string tableName, string propertyName) 
    { 
     this.tableName = tableName; 
     this.propertyName = propertyName; 
    } 

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     if (request.Method.Method == HttpMethod.Get.Method && 
      request.RequestUri.PathAndQuery.StartsWith("/tables/" + tableName, StringComparison.OrdinalIgnoreCase)) 
     { 
      UriBuilder builder = new UriBuilder(request.RequestUri); 
      string query = builder.Query; 
      if (!query.Contains("$expand")) 
      { 
       if (string.IsNullOrEmpty(query)) 
       { 
        query = ""; 
       } 
       else 
       { 
        query = query + "&"; 
       } 

       query = query + "$expand=" + propertyName; 
       builder.Query = query.TrimStart('?'); 
       request.RequestUri = builder.Uri; 
      } 
     } 

     return await base.SendAsync(request, cancellationToken); 
     return result; 
    } 
} 

而且你會通過創建MobileServiceClient一個新實例使用的處理程序:

var expandedClient = new MobileServiceClient(
    App.MobileService.ApplicationUrl, 
    App.MobileService.ApplicationKey, 
    new MyExpandPropertyHandler("Place", "Roads")); 
var roadList = await App.MobileService.GetTable<Place>() 
    .LookupAsync(placeId); 
+0

感謝您的這兩個解決方案的詳細回覆!我沒有意識到我可以自定義查詢參數 – zhengbli 2014-09-05 21:10:58