简化方法从通用存储库中检索数据 [英] Simplify method retrieving data from generic repository

查看:81
本文介绍了简化方法从通用存储库中检索数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



 私人异步任务< 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 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆