存储库

时间:2018-01-30 10:21:09

标签: azure azure-mobile-services iqueryable ddd-repositories

我希望我的代理商独立于数据访问技术。目前,我正在开发一个使用Azure移动应用程序服务进行数据访问的Xamrin.Forms应用程序。出于性能和灵活性的原因,我希望我的存储库看起来像下面这样:

Task<IEnumerable<IDomainObject>> GetDomainObjectAsync(Func<IQueryable<IDomainObject>, IQueryable<IDomainObject>> query)

假设我的IDomainObject如下所示:

public interface IDomainObject
{
    string Name { get; }
}

和我的DataAccess对象:

internal class AzureDomainObject : IDomainObject
{
    public string Name { get; set; }
    public string Id { get; set; }
}

据我发现并测试过,我可以执行以下操作来查询我的存储库实现中的数据库:

public async Task<IEnumerable<IDomainObject>> GetDomainObjectAsync(Func<IQueryable<IDomainObject>, IQueryable<IDomainObject>> query)
{
    // _table of type IMobileServiceTable<AzureDomainObject> gotten by MobileServiceClient
    var tableQuery = _table.GetQuery();
    tableQuery.Query = tableQuery.Query.Take(4); // 1) this was for testing and it works (ordering etc also works)
    // tableQuery.Query = query(tableQuery.Query); // 2) this was my initial idea how to use the input param
    await _table.ReadAsync(tableQuery);
}

我现在的问题是如何使用输入参数query替换2)。

tableQuery.Query预计IQueryable<AzureDomainObject>query的类型为IQueryable<IDomainObject>

.Cast<AzureDomainObject>().OfType<AzureDomainObject>()都无法转换。 (IQueryable<IAzureDomainObject>)query;也不起作用。

Cast和OfType抛出NotSupportedException并且强硬投射会抛出InvalidCastException

我还尝试从Expression输入参数中提取query并将其分配给tableQuery.Query。但随后发生运行时异常,它们不兼容。

我的另一个想法是使用ReadAsync(string)重载并传递传递的query参数的字符串表示形式。但是这种方式我不知道如何生成字符串。

所以最后一个问题是:有没有人知道如何从域模型中隐藏AzureDomainObjectIMobileServiceTable,但是在存储库界面中保持IQueryable的灵活性和性能优势? / p>

1 个答案:

答案 0 :(得分:1)

根据你的描述,我检查了这个问题,这是我在这种情况下的实现,你可以参考它们。

<强>型号:

public class TodoItem : IDomainObject
{
    public string Id { get; set; }

    [JsonProperty(PropertyName = "text")]
    public string Text { get; set; }

    [JsonProperty(PropertyName = "complete")]
    public bool Complete { get; set; }
}

public interface IDomainObject
{
    string Id { get; set; }
}

<强>存储库:

public interface IAzureCloudTableRepository<T> where T : IDomainObject
{
    Task<IEnumerable<T>> GetDomainObjectAsync(Func<IQueryable<T>, IQueryable<T>> query);
}


public class AzureCloudTableRepository<T> : IAzureCloudTableRepository<T> where T : IDomainObject
{
    IMobileServiceTable<T> table;

    public AzureCloudTableRepository(MobileServiceClient client)
    {
        this.table = client.GetTable<T>();
    }

    public async Task<T> CreateItemAsync(T item)
    {
        await table.InsertAsync(item);
        return item;
    }

    public async Task<IEnumerable<T>> GetDomainObjectAsync(Func<IQueryable<T>, IQueryable<T>> query)
    {
        var tableQuery = this.table.CreateQuery();
        tableQuery.Query = tableQuery.Query.Take(4); //the internal fixed query
        tableQuery.Query = query(tableQuery.Query);  //the external query
        return await tableQuery.ToEnumerableAsync();
    }
}

<强> TEST:

var mobileService = new MobileServiceClient("https://{your-app-name}.azurewebsites.net");
var todoitem = new AzureCloudTableRepository<TodoItem>(mobileService);
var items = await todoitem.GetDomainObjectAsync((query) =>
{
    return query.Where(q => q.Text!=null);
});

enter image description here