【问题标题】:Before saving object, add a role. Where should this logic?在保存对象之前,添加一个角色。这个逻辑应该在哪里?
【发布时间】:2011-10-08 13:52:21
【问题描述】:

在我的应用程序中,我有以下代码:

public class Couple
{
    public List<Role> Roles { get; set; };
    public Couple()
    {
        //How can I add the role in the constructor?
        //Is it correct to refer to the repository?
        //If so, this will impact on my EF Code First
    }
}

public class Role
{
    public string Name { get; set; };
}

public class DataContext : DbContext
{
    DbSet<Couple> Couples { get; set; }
    DbSet<Role> Roles { get; set; }
}

public interface IRepository
{
    void AddCouple(Couple couple);
}

public class Repository : IRepository
{
    DataContext db = new DataContext();

    public void AddCouple(Couple couple)
    {
        var role = (from r in db.Roles
                        where r.Name == "Couple"
                        select r).SingleOrDefault();

    couple.Roles.Add(role); //This is a correct place?
        db.Couples.Add(entity);

        db.SaveChanges();
    }
}

我还有一个带有假存储库的测试项目:

public class FakeRepository : IRepository
{
    List<Couple> Couples = new List<Couple>();
    ListRole> Roles = new List<Role>();

    public void AddCouple(Couple couple)
    {
        var role = (from r in Roles
                        where r.Name == "Couple"
                        select r).SingleOrDefault();

        couple.Roles.Add(role);
        Couples.Add(entity);
    }
}

AddCouple 方法中的Repository 类中,我添加了角色。但我认为这不是正确的地方。

我的问题是在哪里放置逻辑,查看role 存储库并填充couple 的角色列表。

并且能够继续构建测试。

【问题讨论】:

    标签: asp.net-mvc-3 unit-testing architecture repository-pattern


    【解决方案1】:

    您的存储库中的以下行有问题:

    DataContext db = new DataContext();
    

    它会阻止你对这个类进行孤立的单元测试,因为你已经将它与某些特定的数据访问类紧密联系在一起。

    你可以定义一个抽象:

    public interface IMyDataContext
    {
        DbSet<Couple> Couples { get; set; }
        DbSet<Role> Roles { get; set; }
        int SaveChanges();
    }
    

    然后提供一些实现:

    public class DataContext : DbContext, IMyDataContext
    {
        public DbSet<Couple> Couples { get; set; }
        public DbSet<Role> Roles { get; set; }
    }
    

    现在您的存储库应该只适用于抽象:

    public class Repository : IRepository
    {
        private readonly IMyDataContext _db;
        public Repository(IMyDataContext db)
        {
            _db = db;
        }
    
        public void AddCouple(Couple couple)
        {
            var role = (from r in _db.Roles
                        where r.Name == "Couple"
                        select r).SingleOrDefault();
    
            couple.Roles.Add(role); 
            _db.Couples.Add(entity);
            _db.SaveChanges();
        }
    }
    

    现在在您的单元测试中,您可以使用模拟框架向存储库提供虚假上下文,并能够对其进行单独测试。

    【讨论】:

    • 好的,但即便如此,现在我的DbContext 我必须复制逻辑:var role = (from r in _db.Roles where r.Name == "Couple" select r).SingleOrDefault(); couple.Roles.Add(role); 我需要在保存之前将role 添加到couple,但不要复制代码.我不知道在哪里。
    • @Riderman de Sousa Barbosa,我不明白你在说什么重复。我以为您是在问如何单独对存储库进行单元测试。
    • 要测试AddCouple方法,我需要集中逻辑来添加Role。否则,测试存储库是没有意义的,因为存储库将表现为假存储库,而生产将有另一个。 查看此代码: var role = (from r in _db.Roles where r.Name == "Couple" select r). SingleOrDefault (); couple.Roles.Add (role);
    • @RidermandeSousaBarbosa,通常存储库应该只包含对您的业务实体的简单 CRUD 操作。您应该有一个服务层聚合多个存储库,您可以在其中定义更复杂的操作。
    • @RidermandeSousaBarbosa,当您与实体进行复杂的业务操作时,服务层很有用。
    猜你喜欢
    • 2012-10-06
    • 2011-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-04
    • 1970-01-01
    • 2014-12-09
    相关资源
    最近更新 更多