c# - 从 Redis 映射数据的有效方法

标签 c# redis automapper servicestack.redis

我正在使用 Redis 和 ServiceStack.Redis 作为客户端。我最初使用“AutoMapper”将缓存的对象映射到域对象中,但这非常慢。使用其他人的示例,我设置了一个自定义映射器,但这也非常慢。

下面的代码有什么明显的错误吗?从 Redis 映射 1000 个项目需要 4-5 秒。

这是引入延迟的“GetByIds”客户端方法,但我想要一种有效的方法来存储集合,因为 Redis 中的 ID 列表看不到另一种将它们转换为域对象列表的方法。

谢谢!

interface IMapToNew<TSource, TTarget>
{
    TTarget Map(TSource source);
}

interface IMapToExisting<TSource, TTarget>
{
    void Map(TSource source, TTarget target);
}

class FullEmployeeMapper : IMapToNew<Employee, FullEmployee>
{
    public FullEmployee Map(Employee source)
    {
        FullEmployee employee = new FullEmployee()
        {
            Id = source.Id,
            Age = source.Age,
            BirthDate = source.BirthDate,
            Name = source.Name
        };

        var mapper = new FullRoleMapper();
        var client = new RedisClient("localhost");

        employee.Roles =
            client
                .As<Role>()
                .GetByIds(source.Roles)
                .Select(r => mapper.Map(r))
                .ToList();

        return employee;
    }
}

class FullRoleMapper : IMapToNew<Role, FullRole>
{
    public FullRole Map(Role source)
    {
        FullRole role = new FullRole()
        {
            Id = source.Id,
            RoleName = source.RoleName
        };

        return role;
    }
}

class FullEmployee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int? Age { get; set; }
    public DateTime? BirthDate { get; set; }
    public IList<FullRole> Roles { get; set; }
}

class FullRole
{
    public int Id { get; set; }
    public string RoleName { get; set; }
}

class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int? Age { get; set; }
    public DateTime? BirthDate { get; set; }
    public IList<int> Roles { get; set; }

    public Employee(int EmployeeId, string Name)
    {
        this.Id = EmployeeId;
        this.Name = Name;
    }
}

class Role
{
    public int Id { get; set; }
    public string RoleName { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var client = new RedisClient("localhost");
        var employeeClient = client.As<Employee>();

        var allEmployees = employeeClient.GetAll();

        var allFullEmployees = 
            allEmployees
                .Select(e => mapper.Map(e))
                .ToList();
    }
}

最佳答案

您可以使用延迟加载,以便仅在需要时加载 Roles 集合。这是通过在您的 FullEmployee 实体中注入(inject)角色存储库来完成的。

您也可以一次加载所有角色:在您的 FullEmployeeMapper 中保留角色字典并在加载时填充它,然后在查询缓存之前检查它。希望您为每个工作单元重新创建一个实例,以便字典对每个新工作都是新鲜的,并且您可以避免多线程问题。

使用 List 的示例实现:

class FullEmployeeMapper : IMapToNew<Employee, FullEmployee>
{
    private List<FullRole> _roles = new List<FullRole>();
    public FullEmployee Map(Employee source)
    {
        FullEmployee employee = new FullEmployee()
        {
            Id = source.Id,
            Age = source.Age,
            BirthDate = source.BirthDate,
            Name = source.Name
        };

        var mapper = new FullRoleMapper();
        var client = new RedisClient("localhost");

        employee.Roles = _roles.Where(r => source.Roles.Contains(r.Id)).ToList();
        if (employee.Roles.Count != source.Roles.Count)
        {
            var newRoles = client
                .As<Role>()
                .GetByIds(source.Roles.Except(employee.Roles.Select(r => r.Id)))
                .Select(r => mapper.Map(r)))
                .ToList();
            employee.Roles.AddRange(newRoles);
            _roles.AddRange(newRoles);
        }
        return employee;
    }
}

关于c# - 从 Redis 映射数据的有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25814496/

相关文章:

c# - 比较 'int' 和 'null' 编译

c# - 如何通过 linq 查询对组中的元素进行排序,然后选择第一个?

带有 redis 的 MongoDB

node.js - 如何在 node.js 中使用 redis 进行身份验证?

c# - 已添加具有相同键的项目 c# 错误

c# - Web API 2 自定义身份验证

redis - redis 输出中的额外斜杠

c# - 为什么 AutoMapper 嵌套映射在没有内部类型的 CreateMap 的情况下工作

c# - 使用 Automapper 在 DataReader 中将字符串转换为 bool 值

.net - 为什么 AutoMapper 仅在列表中的第一个元素上使用我的配置?