2014-09-05 28 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