我希望我的代理商独立于数据访问技术。目前,我正在开发一个使用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
参数的字符串表示形式。但是这种方式我不知道如何生成字符串。
所以最后一个问题是:有没有人知道如何从域模型中隐藏AzureDomainObject
和IMobileServiceTable
,但是在存储库界面中保持IQueryable
的灵活性和性能优势? / p>
答案 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);
});