简化方法从通用存储库中检索数据 [英] Simplify method retrieving data from generic repository
问题描述
私人异步任务< string> GetByIdFrom(EntityArgs参数)
{
string content = null;
switch(args.CollectionName.ToLowerInvariant())
{
case Common.WorkingSite:
var workingsite = await(new Repository< WorkingSite>())
。 GetByKeyAsync(args.Id);
if(workingsite!= null)
content = workingsite.Content;
休息;
case Common.ProductInstruction:
var productInfo = await(new Repository< ProductInstruction>())
.GetByKeyAsync(args.Id);
if(productInfo!= null)
content = productInfo.Content;
休息;
case Common.Resource:
var resource = await(new Repository< Resource>())
.GetByKeyAsync(args.Id);
if(resource!= null)
content = resource.Content;
休息;
默认值:
Logger.Warn(GetById():Table {0} not found,args.CollectionName);
休息;
}
返回内容;
$您可以看到开关
是关于重复和所有个案
返回内容
由 args.Id code>如果 EntityArgs
有效。内容始终是复杂的JSON。
$ b $ < CollectionName
属性是 string $ c $因为请求来自JavaScript客户端; CollectionName
简单地标识.NET元件上的 SQLite
表。
所有上述的类 Repository< T>
实现了相同的抽象基础实体
。
[JsonObject]
public abstract class实体
{
protected Entity()
{}
[PrimaryKey]
[JsonProperty(PropertyName =id)]
public int Id {get;组; }
[JsonIgnore]
public string Content {get;组; }
$ b 存储库的实现如下,其中 SQLiteDataProvider
是连接到本地 SQLite
数据库的 SQLite-net
ORM的包装。
public class Repository< T> T:new()
{
private private readonly Logger _logger = LogManager.GetCurrentClassLogger();
///< summary>
///通过主键获取
///< / summary>
公共虚拟异步任务< T> GetByKeyAsync(object key)
{
var item = default(T);
try
{
item = await SQLiteDataProvider.Connection.GetAsync< T>(key);
catch(Exception e)
{
if((e is InvalidOperationException)&& e.Message.Contains(no elements))
{
_logger.Info(GetByKeyAsync< {0}> - {1},(typeof(T))。Name,e.Message);
}
else
{
_logger.Error(e);
throw;
}
}
退货项目;
}
// ...其他方法
}
我非常肯定我应该能够摆脱整个 switch
语句,并且只需调用类似于
var item = await(new Repository< Entity>())。GetByKeyAsync(args.Id);
返回项目!= null? item.Content:null;
......当然,因为我需要知道具体对应的类数据库表。
我无法理解它。想法?
解决方案 Sicne所有类型的实现实体
一个需要type参数继承的泛型方法,以便您可以访问 Content
属性。
私人异步任务< string> GetByIdFrom< T>(EntityArgs args)
其中T:Entity
{
T entity = await(new Repository< T>))。GetByKeyAsync(args.Id);
if(entity!= null)
return entity.Content;
返回null;
$ / code>
请注意,您仍然需要一个包含您的交换机的非泛型方法您根据 args.CollectionName
选择要遵循的路径。但至少它变得更简洁:
私人异步任务< string> GetByIdFrom(EntityArgs args)
{
switch(args.CollectionName.ToLowerInvariant())
{
case工作站点:$ b $ b return GetByIdFrom<工作站点>(args);
case ProductInstruction:
return GetByIdFrom<产品说明>(args);
case资源:
return GetByIdFrom< Resource>(args);
默认值:
Logger.Warn(GetById():Table {0} not found,args.CollectionName);
休息;
}
}
I have a method that retrieves data from different repositories based on given arguments.
private async Task<string> GetByIdFrom(EntityArgs args)
{
string content = null;
switch (args.CollectionName.ToLowerInvariant())
{
case Common.WorkingSite:
var workingsite = await (new Repository<WorkingSite>())
.GetByKeyAsync(args.Id);
if (workingsite != null)
content = workingsite.Content;
break;
case Common.ProductInstruction:
var productInfo = await (new Repository<ProductInstruction>())
.GetByKeyAsync(args.Id);
if (productInfo != null)
content = productInfo.Content;
break;
case Common.Resource:
var resource = await (new Repository<Resource>())
.GetByKeyAsync(args.Id);
if (resource != null)
content = resource.Content;
break;
default:
Logger.Warn("GetById(): Table {0} not found", args.CollectionName);
break;
}
return content;
}
As you can see the switch
is all about repetition and all cases
return Content
by args.Id
if EntityArgs
are valid. Content is always complex JSON.
The CollectionName
property is string
because request is coming from JavaScript client; CollectionName
simply identifies SQLite
table on .NET parts.
All of the above classes for Repository<T>
implements same abstract base Entity
.
[JsonObject]
public abstract class Entity
{
protected Entity()
{}
[PrimaryKey]
[JsonProperty(PropertyName = "id")]
public int Id { get; set; }
[JsonIgnore]
public string Content { get; set; }
}
Repository is implemented as follows, where SQLiteDataProvider
is wrapper around SQLite-net
ORM, connected to local SQLite
database.
public class Repository<T> where T : new()
{
private readonly Logger _logger = LogManager.GetCurrentClassLogger();
/// <summary>
/// Get by primary key
/// </summary>
public virtual async Task<T> GetByKeyAsync(object key)
{
var item = default(T);
try
{
item = await SQLiteDataProvider.Connection.GetAsync<T>(key);
}
catch (Exception e)
{
if ((e is InvalidOperationException) && e.Message.Contains("no elements"))
{
_logger.Info("GetByKeyAsync<{0}> - {1}", (typeof(T)).Name, e.Message);
}
else
{
_logger.Error(e);
throw;
}
}
return item;
}
// ...other methods
}
I'm pretty sure I should be able to get rid of whole switch
statement and just call something like
var item = await (new Repository<Entity>()).GetByKeyAsync(args.Id);
return item != null ? item.Content : null;
...of course above won't work since I need to know the concrete class that corresponds underlying database table.
I just can't get my head around it. Ideas?
解决方案 Sicne all your types implement Entity
, you can make a generic method that requires the type argument to inherit from it so you can access the Content
property.
private async Task<string> GetByIdFrom<T>(EntityArgs args)
where T : Entity
{
T entity = await (new Repository<T>()).GetByKeyAsync(args.Id);
if (entity != null)
return entity.Content;
return null;
}
Note that you will still need a non-generic method that contains your switch so you choose which path to follow based on args.CollectionName
. But at least it becomes a lot more concise:
private async Task<string> GetByIdFrom(EntityArgs args)
{
switch (args.CollectionName.ToLowerInvariant())
{
case WorkingSite:
return GetByIdFrom<WorkingSite>(args);
case ProductInstruction:
return GetByIdFrom<ProductInstruction>(args);
case Resource:
return GetByIdFrom<Resource>(args);
default:
Logger.Warn("GetById(): Table {0} not found", args.CollectionName);
break;
}
}
这篇关于简化方法从通用存储库中检索数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!