Azure移动服务C#无法返回子实体。

8

我在使用基于C#的Azure移动服务时遇到了困难,与此相关的内容是IT技术。我无法让查询操作返回子属性值,这让我十分苦恼。

我已经修改了默认项目中的待办事项,但是仍然无法解决问题。

public class TodoItem : EntityData
{
    public TodoItem()
    {
        this.Numbers = new Collection<TodoItemNumbers>(new List<TodoItemNumbers>
        {
            new TodoItemNumbers{Value = 1},
            new TodoItemNumbers{Value = 2},
            new TodoItemNumbers{Value = 3},
            new TodoItemNumbers{Value = 4},
            new TodoItemNumbers{Value = 5},
        });
    }
    public virtual ICollection<TodoItemNumbers> Numbers { get; set; }
    public string Text { get; set; }
    public bool Complete { get; set; }
}

然后我定义了TodoItemNumbers类如下:

public class TodoItemNumbers : EntityData
{
    private int _value;

    public int Value
    {
        get { return _value; }
        set
        {
            _value = value;
            Id = value.ToString();
        }
    }

    public string TodoItemId { get; set; }
}

在TodoItemController中,我覆盖了Query方法,代码如下:

protected override IQueryable<TodoItem> Query()
{
    return base.Query().Include(x => x.Numbers);
}

当我使用Fiddler进行请求时,这些操作都无法返回Numbers属性。在一瞬间的疯狂中,我还修改了控制器的Initialize方法以包含以下内容:

protected override void Initialize(HttpControllerContext controllerContext)
{
    base.Initialize(controllerContext);
    myContext context = new myContext();
    context.Configuration.LazyLoadingEnabled = false;
    context.Configuration.ProxyCreationEnabled = false;
    DomainManager = new EntityDomainManager<TodoItem>(context, Request, Services);
}

请注意,懒加载和代理创建都已关闭。 有人知道如何在这个简单的场景中胜出吗?我对此并不感觉良好。
更新: 正如我在下面回答的那样,通过在查询中添加 $ expand,我能够使服务返回数据。但是,现在我真的卡在了如何让客户端向请求添加该参数上。它始终只返回基本数据。
    var data = await App.MobileService.GetTable<TodoItem>()
        .ToListAsync();

该方法不会返回子属性,而且结果类型中也没有包含选项。


如果您从集合属性中删除“virtual”,则它将不使用延迟加载(这并不能回答我们的问题,但可能是有用的信息)。 - BrunoLM
5个回答

2

我的错误在于没有真正考虑到OData这部分。一旦我查询了

http://localhost:51025/tables/todoitem?$expand=Numbers

替代

http://localhost:51025/tables/todoitem

它神奇地出现了。现在我该如何让它在客户端API中体现出来呢...? 更新 我在客户端使用以下代码成功实现了此功能

var json =
                    await
                        App.MobileService.GetTable("TodoItem")
                            .ReadAsync("$expand=Numbers");
JsonConvert.DeserializeObject<TodoItem>(json.First.ToString());

但是必须有更好的方法。

2

还可以通过在客户端添加处理程序来实现:

var client = new MobileServiceClient("http://xxxxxx/", null, new ODataParameterHandler());

public class ODataParameterHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        UriBuilder builder = new UriBuilder(request.RequestUri);

        builder.Query = builder.Query
            .Replace("expand", "$expand")
            .TrimStart('?');

        request.RequestUri = builder.Uri;

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

使用方法:

var test = await client.GetTable<TodoItem>()
    .WithParameters(new Dictionary<string, string> { { "expand", "Something" } })
    .ToListAsync();

1

不要覆盖Query方法,而是让GetAllTodoItems方法看起来像这样:

public IList<TodoItem> GetAllTodoItems()
{
    return context.TodoItems.Include( "Numbers" ).ToList();
}

这是一个替代 $expand hack 的方法。我在探索 Azure App Service 移动应用时发现了它。如果您最初尝试的仅使用 Include 调用进行链接,那么这可能更有意义,但是我希望找出为什么不起作用。请注意保留 HTML 标签。

0

我以为在可获取的后面是 .Include(x => x.Numbers)


不,那就是我代码里的内容。我以为那也应该可以工作。 - Dylan

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接