我正在使用 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/