EF存储库模式多对多插入

时间:2011-12-20 14:24:34

标签: c# asp.net entity-framework-4 many-to-many repository-pattern

我们有两张桌子:

表权限:

public class Authority
{
   public int ID {get;set;}
   public string Name{get;set;}
      ...
}

表代理

public class Agent
{
  public int ID{get;set;}
  public int FirstName{get;set;}
}

我们在这两个表之间存在多对多的关系:

public class AuthorityConfiguration : EntityTypeConfiguration<Authority>
{
    public AuthorityConfiguration()
        : base()
    {
        HasKey(p => p.ID);

        HasMany(p => p.Agents).WithMany(a => a.Authorities).Map(mc =>
            {
                mc.MapLeftKey("AuthorityID");
                mc.MapRightKey("AgentID");
                mc.ToTable("AuthorityAgent");
            });


        ToTable("Authority");

    }
}

一切都很好。 但是现在我有一个页面来创建表之间的关联,我需要使用Repository Pattern将“authorityAgent”关系插入到我的表中。

问题1:如果我的DAO正在接收权限,我如何获得代理?

AuthorityDAO.cs

public static void InsertAgent(int authorityID, int agentID)
    {
        var dao = new ConcreteDAO<Authority>();

        Authority authority = dao.Single(p => p.ID.Equals(authorityID));

        // I can't do that because the relationship doesn't exist yet.
        var agent = authority.Agents.Where(p => p.ID.Equals(agentID));


        authority.Agents.Add(agent);

        dao.Attach(authority);

        dao.SaveChanges();

    }

我知道我可以在DAO中创建我的上下文来做它,但我会制作模式,不是吗?

我该怎样做上面的方法?

谢谢。

编辑:我找到了一个解决方案,但我不知道这是否是更好的方法:

我为ConcreteDAO创建了一个构造函数,传递了ObjectContext和一个获取对象上下文的方法:

GenericDAO.cs

public ObjectContext GetContext()
{
     return _context;
}

ConcreteDAO.cs

public ConcreteDAO()
{

}

public ConcreteDAO(ObjectContext context)
    : base(context)
{
}

在我的权限DAO.cs内

 public static void InsertAgent(int authorityID, int agentID)
 {
     var dao = new ConcreteDAO<Authority>();
     Authority authority = dao.Single(p => p.ID.Equals(authorityID));
     dao.Attach(authority);

     var daoAgent = new ConcreteDAO<Agent>(dao.GetContext());

     var agent = daoAgent.Single(p => p.ID == agentID);

     authority.Agents.Add(agent);

     dao.SaveChanges();
}

1 个答案:

答案 0 :(得分:2)

我认为您遇到此问题是因为您使用的是没有工作单元模式的存储库模式。您的ConcreteDAO<T>(=实体类型T的通用存储库,我猜)不应创建上下文(=工作单元)。相反,您的消费方法应该明确地创建它并将其注入您需要的所有存储库中。你最后一个方法看起来像这样:

public static void InsertAgent(int authorityID, int agentID)
{
    using (var unitOfWork = new UnitOfWork()) // unit of work = context
    {
        var daoAuthority = new ConcreteDAO<Authority>(unitOfWork);
        var daoAgent = new ConcreteDAO<Agent>(unitOfWork);

        var authority = daoAuthority.Single(p => p.ID.Equals(authorityID));
        var agent = daoAgent.Single(p => p.ID == agentID);

        authority.Agents.Add(agent);

        unitOfWork.SaveChanges();
    }
}

在涉及更改关系的许多情况下,您需要多个通用存储库,但所有工作都必须在相同的上下文中完成。

您可以,顺便说一下,保存以从数据库加载实体,因为您知道主键属性并且不想更改实体本身而只想更改关系。在这种情况下,您可以使用附加的“存根”实体:

public static void InsertAgent(int authorityID, int agentID)
{
    using (var unitOfWork = new UnitOfWork())
    {
        var daoAuthority = new ConcreteDAO<Authority>(unitOfWork);
        var daoAgent = new ConcreteDAO<Agent>(unitOfWork);

        var authority = new Authority { ID = authorityID,
            Agents = new List<Agent>() };
        daoAuthority.Attach(authority);

        var agent = new Agent { ID = agentID };
        daoAgent.Attach(agent);

        authority.Agents.Add(agent);

        unitOfWork.SaveChanges();
    }
}