EF存储库模式多对多插入

发布于 2024-12-21 21:36:48 字数 2301 浏览 1 评论 0原文

我们有 2 个表:

表 Authority:

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

表 Agents

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");

    }
}

一切正常。 但现在我有一个页面来创建表之间的关联,我需要使用存储库模式将关系插入到我的表“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)
{
}

以及在我的 AuthorityDAO 内部。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();
}

We have 2 tables:

Table Authority:

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

Table Agents

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

And we have a relationship many-to-many between these two tables:

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");

    }
}

Everything is working fine.
But now I have a page to create an association between the tables and I need to insert into my table "authorityAgent" the relationship using Repository Pattern.

Problem 1: How can I get the Agent if my DAO is receiving an Authority?

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();

    }

I know I can create my context in the DAO to do it, but I will brake the Pattern, won't I?

How can I do the method above?

Thank you.

EDIT: I found a solution but I don't know if it's the better way to do it:

I created a constructor to my ConcreteDAO passing the ObjectContext and a method to get my object context:

GenericDAO.cs

public ObjectContext GetContext()
{
     return _context;
}

ConcreteDAO.cs

public ConcreteDAO()
{

}

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

And Inside my AuthorityDAO.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();
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

话少心凉 2024-12-28 21:36:48

我认为您遇到这个问题是因为您使用的是存储库模式而不是工作单元模式。您的 ConcreteDAO (=实体类型 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();
    }
}

I think you are having this problem because you are using the Repository pattern without the Unit Of Work pattern. Your ConcreteDAO<T> (= generic repository for entity type T, I guess) should not create a context (=unit of work). Instead your consuming method should create it explicitly and inject it into all repositories you need. You last method would then look like this:

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();
    }
}

In many situations where changing relationships are involved you need more than one generic repository, but all work has to be done within the same context.

You can, btw, save to load the entities from the database because you know the primary key properties and don't want to change the entities themselves but only a relationship. In that case you can work with attached "stub" entities:

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();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文