質問

I have two tables (Table A, Table B) joined with a join table (TableAB) with 3 payload columns. By Payload I mean columns apart from Id, TableAId, and TableBId.

I can insert into all tables successfully, but I need to insert data into one of the payload columns on Insert. I'm using EF 4.3, Fluent API. Can anyone help? Thanks in advance.

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

//I have tried specifically defining the foreign key in fluent, but I really need to understand how I can add the payload properties once I access and edit them.

役に立ちましたか?

解決

Your mapping is not correct for your purpose. If you want to treat OrganisationUser as an intermediate entity between Organisation and User you must create relationships between Organisation and OrganisationUser and between User and OrganisationUser, not directly between Organisation and User.

Because of the intermediate entity which contains its own scalar properties you cannot create a many-to-many mapping. EF does not support many-to-many relationships with "payload". You need two one-to-many relationships:

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 ...
}

In Fluent API you must replace the many-to-many mapping by the following:

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

Your derived DbContext may also contain a separate set for the OrganisationUser entity:

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

It's obvious now how you write something into the intermediate table:

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

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

If you want to make sure that each pair of OrganisationId and UserId can only exist once in the link table, it would be better to make a composite primary key of those two columns to ensure uniqueness in the database instead of using a separate Id. In Fluent API it would be:

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

More details about such a type of model and how to work with it is here:

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top