【问题标题】:M:M Mapping - EF 4.3 CodeFirst (Existing Database)M:M 映射 - EF 4.3 CodeFirst(现有数据库)
【发布时间】:2012-04-13 06:10:32
【问题描述】:

我有两个表(表 A、表 B)与一个包含 3 个有效负载列的连接表 (TableAB) 连接。有效负载是指除 Id、TableAId 和 TableBId 之外的列。

我可以成功插入所有表,但我需要将数据插入到 Insert 上的有效负载列之一。我正在使用 EF 4.3,Fluent API。任何人都可以帮忙吗?提前致谢。

    public class Organisation : EntityBase<int>, IAggregateRoot
       {
    public string Name { get; set; }
    public string Url { get; set; }
    public int CountryId { get; set; }
    public int? OwnershipTypeId { get; set; }
    public int OrganisationStatusId { get; set; }

    public virtual ICollection<Feature> Features { get; set; }
    public virtual ICollection<OrganisationType> OrganisationTypes { get; set; }
    public virtual ICollection<PricePlan> PricePlans { get; set; }
    public virtual ICollection<User> Users { get; set; }

}

    public class User: EntityBase<Guid>, IAggregateRoot
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string JobTitle { get; set; }
    public int?  PhoneCallingCodeId       { get; set; }
    public int?  PhoneAreaCode{ get; set; }
    public string PhoneLocal { get; set; }
    public int? MobileCallingCodeId { get; set; }
    public int? MobileAreaCode { get; set; }
    public string MobileLocal { get; set; }      

    public virtual ICollection<Organisation.Organisation> Organisations { get; set; }

}

   public class OrganisationUser : EntityBase<int>, IAggregateRoot
{
    public DateTime StartDate { get; set; }
    public DateTime? EndDate { get; set; }
    public int OrganisationRoleId {get; set;}//Foreign Key - have tried leaving it out, tried it as public virtual Organisation Organisation {get;set;
    public bool IsApproved { get; set; }
}

     public class SDContext : DbContext 
{      

    public ObjectContext Core
    {
        get
        {
            return (this as IObjectContextAdapter).ObjectContext;
        }
    }
  public IDbSet<User> User { get; set; }

  public IDbSet<Organisation> Organisation { get; set; }

  protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

        modelBuilder.Entity<Organisation>().HasMany(u => u.Users).WithMany(o => o.Organisations).Map(m =>
        {
            m.MapLeftKey("OrganisationId");
            m.MapRightKey("UserId");
            m.ToTable("OrganisationUser");
        });

//我已经尝试在fluent中专门定义外键,但是我真的需要了解如何在访问和编辑它们后添加有效负载属性。

【问题讨论】:

  • 能否请您展示您拥有的类(尤其是它们的导航属性)和 Fluent 映射?
  • 嗨,这真的很重要吗?我知道这些表与 POCO 正确映射,因为 ID 的所有插入都很好。我只是不知道如何访问有效负载列。假设我有一个组织,我正在添加用户、计费计划等,所以我正在查询相关实体,在 foreach 循环中使用 organization.Add(entity) 将集合添加到我的组织中。如何访问有效负载的联接表 - 我已经为联接创建了一个 POCO 类。
  • 是的,这确实很重要,因为围绕您的问题的长时间沉默证明了这一点。直到现在您才得到答案,因为您没有提供必要的详细信息。最后一条语句很重要——你有一个连接表的实体,它会有你的有效负载列,对吧?那么问题出在哪里呢?加载、更改、保存...您可以编辑您的问题(问题下方的“编辑”链接)以添加更多信息。
  • 您不需要发布您的真实代码,只需举例一些与您的真实代码具有相同结构的代码。您可以使用 TableXYZ 之类的傻瓜,但重要的是要知道您拥有哪些实体和导航以及 FK 属性,它是如何在 Fluent API 中映射的,等等。
  • var jointable = new OrganisastionUser{Id=xx, organizationId=organisation.id, userId=user.Id, roleId=1}; xxxx.Add(jointable) - XXXXXXX 是什么???

标签: entity-framework insert many-to-many jointable payload


【解决方案1】:

您的映射不适合您的用途。如果要将OrganisationUser 视为OrganisationUser 之间的中间实体,则必须在OrganisationOrganisationUser 之间以及UserOrganisationUser 之间创建关系,而不是直接在Organisation 和@ 之间创建关系987654330@.

由于包含自己的标量属性的中间实体,您无法创建多对多映射。 EF 不支持与“有效负载”的多对多关系。您需要两个一对多关系:

public class Organisation : EntityBase<int>, IAggregateRoot
{
    // ...
    // this replaces the Users collection
    public virtual ICollection<OrganisationUser> OrganisationUsers { get; set; }
}

public class User : EntityBase<Guid>, IAggregateRoot
{
    // ...
    // this replaces the Organisations collection
    public virtual ICollection<OrganisationUser> OrganisationUsers { get; set; }
}

public class OrganisationUser : EntityBase<int>, IAggregateRoot
{
    public int OrganisationId { get; set; }
    public Organisation Organisation { get; set; }

    public Guid UserId { get; set; }
    public User User { get; set; }

    // ... "payload" properties ...
}

在 Fluent API 中,您必须将多对多映射替换为以下内容:

modelBuilder.Entity<Organisation>()
    .HasMany(o => o.OrganisationUsers)
    .WithRequired(ou => ou.Organisation)
    .HasForeignKey(ou => ou.OrganisationId);

modelBuilder.Entity<User>()
    .HasMany(u => u.OrganisationUsers)
    .WithRequired(ou => ou.User)
    .HasForeignKey(ou => ou.UserId);

您的派生DbContext 还可能包含OrganisationUser 实体的单独集合:

public IDbSet<OrganisationUser> OrganisationUsers { get; set; }

现在你如何在中间表中写入内容很明显了:

var newOrganisationUser = new OrganisastionUser
{
    OrganisationId = 5,
    UserId = 8,
    SomePayLoadProperty = someValue,
    // ...
};

context.OrganisastionUsers.Add(newOrganisastionUser);
context.SaveChanges();

如果你想确保每对OrganisationIdUserId在链接表中只能存在一次,最好将这两列做成一个复合主键,以确保在数据库中的唯一性使用单独的Id。在 Fluent API 中,它将是:

modelBuilder.Entity<OrganisationUser>()
    .HasKey(ou => new { ou.OrganisationId, ou.UserId });

关于这种类型的模型以及如何使用它的更多细节在这里:

Create code first, many to many, with additional fields in association table

【讨论】:

  • 感谢磨坊!我今天就试试。我之前确实读过这个,但我很惊讶现在 EF 不支持这个。非常感谢您的帮助。
  • 您好,这行得通。我仍然遇到问题,但这是因为我使用的是 EntityBase,它试图在我的身份规范列中提供一个 ID。非常感谢您的帮助。谢谢。
  • 根据这种情况调整我的情况,我收到错误 SqlException:外键 'FK_dbo.OrganisationUser_dbo.Organisation_OrganisationId' 在引用表 'dbo.Organisation' 中引用了无效列 'OrganisationId'。无法创建约束。为什么?
  • @EduardoBrites:我只是想建议创建一个关于此的新问题,但我看到你已经有 :) 我不知道答案...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-29
  • 2023-03-25
  • 1970-01-01
  • 1970-01-01
  • 2014-11-01
  • 1970-01-01
相关资源
最近更新 更多