2014-09-12 47 views
0

我在玩Redis,并且以ServiceStack.Redis作为客户端。我最初使用'AutoMapper'将缓存的对象映射到域对象,但这很慢。用别人的例子,我设置了一个自定义映射器,但是这个也非常慢。映射来自Redis的数据的有效方式

下面的代码是否有明显的错误?从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(); 
    } 
} 
+0

映射器都是为了填补一个域对象DTO的VM。相反应该手动完成。您的域对象往往过于复杂(域代码,没有公共默认构造函数,...)以自动映射。 – Guillaume 2015-04-03 07:35:00

回答

0

您可以使用延迟加载,从而Roles收集,如果只需要加载。这是通过在您的FullEmployee实体中注入角色存储库来完成的。

您也可以为所有角色加载一次角色:在您的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; 
    } 
}