EF Core Many to many with same class - asp.net-core

I have City class representing City with its postal code. I have also a Route class representing bus route between two cities. So, i want in my Route class to have cityFrom and cityTwo properties, both with type City - many to many relationship with same class involved.
How can I achieve this with EF Core code first?
Thx!
UPDATE:
My models looks something like this:
public class Route
{
public int Id { get; set; }
public City CityFrom { get; set; }
public City CityTo { get; set; }
}
public class City
{
public int Id { get; set; }
public int PostCode { get; set; }
public string Name { get; set; }
}
Would this solve my problem:
modelBuilder.Entity<Route>()
.HasOne(f => f.CityFrom)
.WithMany()
.HasForeignKey(f => f.CityFromId);
modelBuilder.Entity<Route>()
.HasOne(f => f.CityTo)
.WithMany()
.HasForeignKey(f => f.CityToId);
And also to add int properties CityFromId and CityToId in Route model?

You can achieve many-to-many relationships in ASP.NET Core using Data Annotations
In your requirements, we can introduce a new class named CityRoute that represent many-to-many between the City and the Route
public class Route
{
public int RouteId { get; set; } // change to make it more specific id
public string CityFrom { get; set; }
public string CityTo { get; set; }
public ICollection<CityRoute> CityRoutes { get; set; }
}
public class City
{
public int CityId { get; set; } // change to make it more specific id
public int PostCode { get; set; }
public string Name { get; set; }
public ICollection<CityRoute> CityRoutes { get; set; }
}
// new class
public class CityRoute
{
public City City { get; set; }
public int CityId { get; set; }
public Route Route { get; set; }
public int RouteId { get; set; }
}
Your DataAnnotations can be like this
modelBuilder.Entity<CityRoute>()
.HasKey(cr => new {cr.CityId, cr.RouteId});
I hope this helps you

I wouldn't design this is a many-to-many relation.
Every Route has exactly one FromCity, defined by foreignkey FromCityId.
Every Route has exactly one ToCity, defined by foreignkey ToCityId.
public class Route
{
public int Id { get; set; }
// Every Route has one starting City defined by foreign key:
public int FromCityId { get; set; }
public virtual City FromCity { get; set; }
// Every Route has one termination city, defined by foreign key
public virtual int ToCityId { get; set; }
public virtual City ToCity { get; set; }
...
}
And the DbContext:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Proper name for table of Cities
ModelBuilder.Entity<City>().ToTable("Cities");
// Every Route has one required starting point defined by foreign key
// Several routes may use the same City Id
modelBuilder.Entity<Route>()
.HasRequired(route => route.FromCity)
.WithMany()
.HasForeignKey(route => route.FromCityId)
.WillCascadeOnDelete(false);
// Every Route has one required termination point defined by foreign key
// Several routes may use the same City Id
modelBuilder.Entity<Route>()
.HasRequired(route => route.ToCity)
.WithMany()
.HasForeignKey(route => route.ToCityId)
.WillCascadeOnDelete(false);
base.OnModelCreating(modelBuilder);
If you delete a Route, then you don't want their cities to be deleted, as they might be used by other Routes: hence we don't want cascading on delete CascadeOnDelete(false)

EFCore 3.
Needs its own many to many class.
My problem was: Person to Person relations (n->m)
My solution.
Create a relationship class that implements the many to many.
I chose for the records in the class to have their own ID.
So the relationship class has 1 PK and 2 FKs (both to the Person class).
public class Person
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Relationship> MyRelationships { get; set; }
public List<Relationship> TheirRelationships { get; set; }
}
//MyRelationships for people I added as a relation.
//TheirRelationships for people that added me as a relation.
public class Relationship {
public int RelationshipID { get; set; }
public DateTime Since { get; set; }
//ref to person myrelationships
public int MyID { get; set; }
public Person Me { get; set; }
//ref to person theirrelationships
public int TheirID { get; set; }
public Person They { get; set; }
}
Using add-migration and update-database I learned that in this particular case EFCore cannot resolve which FK to use for which relation.
I solved that using the fluent API.
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//Write Fluent API configurations here
modelBuilder.Entity<Person>()
.HasMany<Relationship>(mr => mr.MyRelationships)
.WithOne(p => p.Me)
.HasForeignKey(m => m.MyID)
.OnDelete(DeleteBehavior.NoAction);
modelBuilder.Entity<Person>()
.HasMany<Relationship>(tr => tr.TheirRelationships)
.WithOne(p => p.They)
.HasForeignKey(t => t.TheirID)
.OnDelete(DeleteBehavior.NoAction);
}
public DbSet<Person> People { get; set; }
public DbSet<Relationship> Relationships { get; set; }
}
Now add-migration xxx will work:
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "People",
columns: table => new
{
ID = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
FirstName = table.Column<string>(nullable: true),
MiddleName = table.Column<string>(nullable: true),
LastName = table.Column<string>(nullable: true),
Email = table.Column<string>(nullable: true),
UserID = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_People", x => x.ID);
table.ForeignKey(
name: "FK_People_AspNetUsers_UserID",
column: x => x.UserID,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_People_UserID",
table: "People",
column: "UserID");
migrationBuilder.CreateTable(
name: "Relationships",
columns: table => new
{
RelationshipID = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Since = table.Column<DateTime>(nullable: false),
Kind = table.Column<int>(nullable: false),
MyID = table.Column<int>(nullable: false),
TheirID = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Relationships", x => x.RelationshipID);
table.ForeignKey(
name: "FK_Relationships_People_MyID",
column: x => x.MyID,
principalTable: "People",
principalColumn: "ID");
table.ForeignKey(
name: "FK_Relationships_People_TheirID",
column: x => x.TheirID,
principalTable: "People",
principalColumn: "ID");
});
migrationBuilder.CreateIndex(
name: "IX_Relationships_MyID",
table: "Relationships",
column: "MyID");
migrationBuilder.CreateIndex(
name: "IX_Relationships_TheirID",
table: "Relationships",
column: "TheirID");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Relationships");
migrationBuilder.DropTable(
name: "People");
}
}

Related

Prevent reference loop properties from serializing

I am getting a buffer exception in one of my unit tests on my controllers for a aspnet.core project.
System.Net.Http.HttpRequestException: Cannot write more bytes to the buffer than the configured maximum buffer size: 2147483647
Digging into it - it is because of a many to many relationship I have configured where I have included the related collection in the response to an entity:
My model(s):
public class Employee
{
[Key] public Guid Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public decimal Salary { get; set; }
public DateTime HireDate { get; set; }
public Guid? ManagerId { get; set; }
public Guid AddressId { get; set; }
public virtual ICollection<EmployeeRole> EmployeeRoles { get; set; }
public virtual Employee Manager { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
public virtual Address Address { get; set; }
public virtual ICollection<EmployeeProject> Projects { get; set; }
}
public class EmployeeProject
{
[Key]
[Column(Order = 1)]
public Guid EmployeeId { get; set; }
[Key]
[Column(Order = 1)]
public Guid ProjectId { get; set; }
public virtual Project Project { get; set; }
public virtual Employee Employee { get; set; }
}
My context configuration:
modelBuilder.Entity<EmployeeProject>(employeeProject =>
{
employeeProject.HasKey(ep => new {ep.EmployeeId, ep.ProjectId});
employeeProject.HasOne(ep => ep.Project)
.WithMany(p => p.EmployeeProjects)
.HasForeignKey(ep => ep.ProjectId);
employeeProject.HasOne(ep => ep.Employee)
.WithMany(e => e.Projects)
.HasForeignKey(ep => ep.EmployeeId);
});
modelBuilder.Entity<Employee>(emp =>
{
emp.HasKey(e => e.Id);
emp.Property(p => p.Id).ValueGeneratedOnAdd();
emp.HasMany(e => e.EmployeeRoles);
emp.HasOne(e => e.Manager).WithMany(e => e.Employees).IsRequired(false);
emp.HasOne(e => e.Address).WithOne(a => a.Employee)
.HasForeignKey<Employee>(e => e.AddressId);
emp.HasMany(e => e.Projects);
});
The problem is I want to include the ICollection with my result of context.Employess. i.e.
ctx.Employees.Include(e => e.Projects).ToListAsync();
This is resulting in all of the related Employee records to be included on each EmployeeProject record, which in turn has the related ICollection and so on. i.e.
[
{
"Id": "1",
"Projects": [
{
"EmployeId": "1"
"ProjectId": "A"
"Employee":
{
"Id": "1"
"Projects": [
{
"EmployeId": "1"
"ProjectId": "A"
"Employee":
And so on.
This when returned in a web response results in a buffer overflow.
I am ignoring the ReferenceLoopHandling in my configuration:
services.AddMvc().AddJsonOptions(options =>
{
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
From the Newtonsoft.Json namespace
/// <summary>Ignore loop references and do not serialize.</summary>
Ignore,
/// <summary>Serialize loop references.</summary>
Serialize,
You can try these attributes :
[JsonObject(IsReference = true)]
This attribute to top of your Class and
[JsonIgnore]
This attribute to top of your Property which is causing the reference loop.
I hope I understand your problem clearly.

How can I make a foreign key relationship between an identity server column and another custom table?

I use identity server.
I know that if I want to add new columns, I make a new class which will inherit from IdentityUser, and in SQL Server with EF, the column will be generated. But I want to have a "Gender" column which will have a foreign key relationship with another custom-made table: "1" will be for "male", "2" for "female" etc.
I also want to make a similar relationship with another table where the programming languages of every employee will be stored.
Is that possible?
public ApplicationUser : IdentityUser
{
public string FullName {get ; set; }
public int GenderId { get ; set ;}
public ICollection<ProgrammingLanguages> PL {get ; set ;}
}
Basically you need to implement one-to-many relationship between User and Gender tables and many-to-many relationship between User and ProgrammingLanguage. Many-to-many relationship requires extra table which will contain foreign keys to User and ProgrammingLanguage tables. You then need to override OnModelCreating() method and don't forget to call the base implementation of OnModelCreating() method so that let the base implementation to setup relationships between identity tables. You can read more on how to implement relationships between entities here. Here is the sample code how this can be done:
public ApplicationUser : IdentityUser
{
public string FullName { get; set; }
public int GenderId { get; set; }
public Gender Gender { get; set; }
public ICollection<UserProgrammingLanguage> UserProgrammingLanguages { get; set;}
}
public class ProgrammingLanguage
{
public int Id { get; set; }
public string Name { get; set; }
}
public class UserProgrammingLanguage
{
public string UserId { get; set; }
public ApplicationUser User { get; set; }
public int ProgrammingLanguageId { get; set; }
public ProgrammingLanguage ProgrammingLanguage { get; set; }
}
public class Gender
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ApplicationContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<Gender> Genders { get; set; }
public DbSet<ProgrammingLanguage> ProgrammingLanguages { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<UserProgrammingLanguage>(entity =>
{
entity.HasKey(pl => { pl.UserId, pl.ProgrammingLanguageId });
entity.HasOne(pl => pl.User)
.WithMany(u => u.UserProgrammingLanguages)
.HasForeignKey(pl => pl.UserId);
entity.HasOne(pl => pl.ProgrammingLanguage)
.WithMany()
.HasForeignKey(pl => pl.ProgrammingLanguageId);
}
builder.Entity<ApplicationUser>(entity =>
{
entity.HasOne(u => u.Gender)
.WithMany()
.HasForeignKey(u => u.GenderId)
.OnDelete(DeleteBehavior.Cascade);
})
base.OnModelCreating(builder);
}
}

EF Core 2.2, owned entities generated as another table when multiple in hierarchy

I have a model with a class Address marked [Owned] and a hierarchy of people (person, customer or employee, then even more subtypes etc). There are addresses at different stages of this hierarchy and all of it ends up in one table as EF Core is limited to table per hierarchy. I expected all the attributes from address to appear multiple times in that person table (once per mention in any of the subtypes) however it doesn't appear at all! Instead i see FK for each of them and a separate Address table.
Does EF Core not support multiple owned members of the same type? If not is there anything i should do? I don't have any fluent API / specific configuration that could interfere with the defaults (new empty console project, only config line is .UseSQLServer(connectionstring)
Sample code bellow :
public class SampleContext : DbContext
{
public virtual DbSet<Address> Addresses { get; set; }
public virtual DbSet<Customer> Customers { get; set; }
public virtual DbSet<Employee> Employees { get; set; }
public virtual DbSet<Person> Persons { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer("my connection string here");
}
base.OnConfiguring(optionsBuilder);
}
}
[Owned]
public class Address
{
public int Id { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string AddressLine3 { get; set; }
public string City { get; set; }
}
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
}
public class Employee : Person
{
public Address Address { get; set; }
}
public class Customer : Person
{
public Address DeliveryAddress { get; set; }
public Address InvoicingAddress { get; set; }
}
Expected Person table :
DeliveryAddressAddressLine1
DeliveryAddressAddressLine2
DeliveryAddressAddressLine3
DeliveryAddressAddressCity
InvoicingAddressAddressLine1
InvoicingAddressAddressLine2
InvoicingAddressAddressLine3
InvoicingAddressAddressCity
EmployeeAddressAddressLine1
EmployeeAddressAddressLine2
EmployeeAddressAddressLine3
EmployeeAddressAddressCity
Generated Person table (+ an unexpected Address table):
EmployeeAddressAddressId
DeliveryAddressAddressId
InvoicingAddressAddressId
Edit : updated the question, added the context definition and noticed i had Addresses as a DbSet so i assume this may be the cause, removing it gives me the following error :
Cannot use table 'Person' for entity type 'Customer.DeliveryAddress#Address' since it is being used for entity type 'Employee.Address#Address' and there is no relationship between their primary keys.`
According to EF Core Owned Entity Types documentation:
Inheritance hierarchies that include owned entity types are not supported
You can overcome this problem by moving public Address Address { get; set; }, public Address DeliveryAddress { get; set; } and public Address InvoicingAddress { get; set; } navigation properties from Employee and Customer to the base class Person as follows:
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public Address Address { get; set; }
public Address DeliveryAddress { get; set; }
public Address InvoicingAddress { get; set; }
}
Then configure with fluent API to override the Navigation_OwnedEntityProperty rule for owned entity column name as follows:
modelBuilder.Entity<Person>().OwnsOne(p => p.Address,
a =>
{
a.Property(p => p.AddressLine1).HasColumnName("EmployeeAddressLine1");
a.Property(p => p.AddressLine2).HasColumnName("EmployeeAddressLine2");
a.Property(p => p.AddressLine2).HasColumnName("EmployeeAddressLine3");
a.Property(p => p.City).HasColumnName("EmployeeAddressCity");
}).OwnsOne(p => p.DeliveryAddress,
a =>
{
a.Property(p => p.AddressLine1).HasColumnName("DeliveryAddressLine1");
a.Property(p => p.AddressLine2).HasColumnName("DeliveryAddressLine2");
a.Property(p => p.AddressLine2).HasColumnName("DeliveryAddressLine3");
a.Property(p => p.City).HasColumnName("DeliveryAddressCity");
}).OwnsOne(p => p.InvoicingAddress,
a =>
{
a.Property(p => p.AddressLine1).HasColumnName("InvoicingAddressLine1");
a.Property(p => p.AddressLine2).HasColumnName("InvoicingAddressLine2");
a.Property(p => p.AddressLine2).HasColumnName("InvoicingAddressLine3");
a.Property(p => p.City).HasColumnName("InvoicingAddressCity");
});
Now you if you don't want to move public Address Address { get; set; }, public Address DeliveryAddress { get; set; } and public Address InvoicingAddress { get; set; } navigation properties from Employee and Customer to the base class Person then you have to create separate tables from each address types as follows:
modelBuilder.Entity<Employee>().OwnsOne(p => p.Address,
a =>
{
a.ToTable("EmployeeAddresses");
});
modelBuilder.Entity<Customer>().OwnsOne(p => p.DeliveryAddress,
a =>
{
a.ToTable("DeliveryAddresses");
}).OwnsOne(p => p.InvoicingAddress,
a =>
{
a.ToTable("InvoicingAddresses");
});

Self Referencing Many-to-Many relations

I have an Ticket entity:
public class Ticket
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<Relation> RelatedTickets { get; set; }
}
I want to setup many-to-many self-relations in Entity Framework Core, so i made two one-to-many relations:
public class Relation
{
[Required, ForeignKey("TicketFrom")]
public int FromId { get; set; }
[Required, ForeignKey("TicketTo")]
public int ToId { get; set; }
public virtual Ticket TicketFrom { get; set; }
public virtual Ticket TicketTo { get; set; }
}
I've tried to create the relationship using fluent API:
builder.Entity<Relation>()
.HasKey(uc => new { uc.FromId, uc.ToId });
builder.Entity<Relation>()
.HasOne(c => c.TicketFrom)
.WithMany(p => p.RelatedTickets)
.HasForeignKey(pc => pc.FromId);
builder.Entity<Relation>()
.HasOne(c => c.TicketTo)
.WithMany(p => p.RelatedTickets)
.HasForeignKey(pc => pc.ToId);
But in result i have an error:
Cannot create a relationship between 'Ticket.RelatedTickets' and
'Relation.TicketTo', because there already is a relationship between
'Ticket.RelatedTickets' and 'Relation.TicketForm'. Navigation
properties can only participate in a single relationship.
The possible solution is to add Parent relation directly to TicketEntity:
public class Ticket
{
public int Id { get; set; }
[Required, ForeignKey("ParentRelation")]
public Nullable<int> ParentRelationId { get; set; }
public virtual Ticket ParentRelation {get;set;}
public virtual ICollection<Ticket> RelatedTickets { get; set; }
...
}
With fluent api like this:
modelBuilder.Entity<Ticket> =>
{
entity
.HasMany(e => e.RelatedTickets)
.WithOne(e => e.ParentRelation)
.HasForeignKey(e => e.ParentRelationId );
});
But it looks 'dirty' to store parent relation like this.
What is the right approach?
It's not possible to have just one collection with relations. You need two - one with relations the ticket equals TicketFrom and second with relations the ticket equals TicketTo.
Something like this:
Model:
public class Ticket
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<Relation> RelatedTo { get; set; }
public virtual ICollection<Relation> RelatedFrom { get; set; }
}
public class Relation
{
public int FromId { get; set; }
public int ToId { get; set; }
public virtual Ticket TicketFrom { get; set; }
public virtual Ticket TicketTo { get; set; }
}
Configuration:
modelBuilder.Entity<Relation>()
.HasKey(e => new { e.FromId, e.ToId });
modelBuilder.Entity<Relation>()
.HasOne(e => e.TicketFrom)
.WithMany(e => e.RelatedTo)
.HasForeignKey(e => e.FromId);
modelBuilder.Entity<Relation>()
.HasOne(e => e.TicketTo)
.WithMany(e => e.RelatedFrom)
.HasForeignKey(e => e.ToId);
Note that a solution using Parent is not equivalent, because it would create one-to-many association, while if I understand correctly you are seeking for many-to-many.
Here is very good explanation how to make many-to-many relationship in EF Core
Many-to-many self referencing relationship
Every collection or reference navigation property can only be a part of a single relationship. While many to many relationship with explicit join entity is implemented with two one to many relationships. The join entity contains two reference navigation properties, but the main entity has only single collection navigation property, which has to be associated with one of them, but not with both.
builder.Entity<Relation>()
.HasKey(uc => new { uc.FromId, uc.ToId });
builder.Entity<Relation>()
.HasOne(c => c.TicketFrom)
.WithMany() // <-- one of this must be empty
.HasForeignKey(pc => pc.FromId)
.OnDelete(DeleteBehavior.Restrict);
builder.Entity<Relation>()
.HasOne(c => c.TicketTo)
.WithMany(p => p.RelatedTickets)
.HasForeignKey(pc => pc.ToId);
Just make sure that WithMany exactly matches the presence/absence of the corresponding navigation property.
Note that you have to turn the delete cascade off.
#IvanStoev is correct. This is an example of a more general self referencing many to many relationship with many parents and many children.
public class Ticket
{
[Key]
public int Id { get; set; }
public string Title { get; set; }
public List<TicketTicket> TicketChildren { get; set; }
public List<TicketTicket> TicketParents { get; set; }
}
public class TicketTicket
{
public int TicketChildId { get; set; }
public Ticket TicketChild { get; set; }
public int TicketParentId { get; set; }
public Ticket TicketParent { get; set; }
}
modelBuilder.Entity<TicketTicket>()
.HasKey(tt => new {tt.TicketChildId, tt.TicketParentId});
modelBuilder.Entity<Ticket>()
.HasMany(t => t.TicketChildren)
.WithOne(tt => tt.ProductParent)
.HasForeignKey(f => tt.ProductParentId);
modelBuilder.Entity<Ticket>()
.HasMany(t => t.TicketParents)
.WithOne(tt => tt.TicketChild)
.HasForeignKey(tt => tt.TicketChildId);

How to use composite Ids in one-to-many mappings in fluent nhibernate?

I got a scenario where a composite Id uniquely identifies an entity. I defined the MSSQL to have a multiple primary key on those fields. In addition I would like an auto-incremented id to be used for referencing a one-to-many relationship. Here's the schema:
public class Character
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual Region Region { get; set; }
public virtual string Realm { get; set; }
public virtual IList<CharProgression> Progression { get; set; }
}
public class CharProgression
{
public virtual int Id { get; set; }
public virtual Character Character { get; set; }
public virtual Stage Stage { get; set; }
public virtual int ProgressionPoints { get; set; }
public virtual int NumOfSaves { get; set; }
}
public class Stage
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
}
The mappings look like this:
class CharacterMap : ClassMap<Character>
{
public CharacterMap()
{
Table("characters");
Id(ch => ch.Id, "id").GeneratedBy.Identity().Not.Nullable();
CompositeId().KeyProperty(ch => ch.Region, "region")
.KeyProperty(ch => ch.Realm, "realm")
.KeyProperty(ch => ch.Name, "name");
HasMany<CharProgression>(ch => ch.Progression).Inverse().Cascade.All();
}
}
class CharProgressionMap : ClassMap<CharProgression>
{
public CharProgressionMap()
{
Table("char_progression");
CompositeId().KeyReference(cprog => cprog.Character, "char_id",
.KeyReference(cprog => cprog.Stage, "stage_id");
Id(cprog => cprog.Id, "id").GeneratedBy.Identity().Not.Nullable();
Map(cprog => cprog.ProgressionPoints, "progression_points");
Map(cprog => cprog.NumOfSaves, "num_of_saves");
}
}
public class StageMap : ClassMap<Stage>
{
public StageMap()
{
Table("stages");
Id(st => st.Id, "id").GeneratedBy.Identity().Not.Nullable();
Map(st => st.Name, "name");
Map(st => st.Description, "description");
}
}
Now, the thing is that I would like to use SaveOrUpdate() on a character and use the composite id for the update, since the character uniqueness is defined by those 3 fields - region, realm, name.
However, when I am referencing the Character from CharProgression, I don't want to use the composite Id as I don't want the char_progression table to hold 3 fields for identifying a character, a simple Id is enough... which is why I also defined an IDENTITY id on the Character entity.
Is what i'm trying possible? or is there another way to achieve this?
Thanks :)