EF Code First relations and associative entity - entity-framework

So I need to have User, Companies and Channels.
User:
is tied to one Company
Channel:
is tied to one Company
can have many users
Company:
can have many users
can have many channels
public class User {
public long Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public virtual Company Company { get; set; }
public virtual ICollection<Channel> Channels { get; set; }
}
public class Company {
public long Id { get; set; }
public string Name { get; set; }
public virtual ICollection<User> Users { get; set; }
public virtual ICollection<Channel> Channels { get; set; }
}
public class Channel {
public long Id { get; set; }
public string Name { get; set; }
public virtual ICollection<User> Users { get; set; }
public virtual Company Company { get; set; }
}
public class CompanyUser {
public long Id { get; set; }
public long CompanyId { get; set; }
public virtual Company Company { get; set; }
public long UserId { get; set; }
public virtual User User { get; set; }
public bool IsOwner { get; set; }
public bool ChannelLimit { get; set; }
}
public class ChannelUser {
public long Id { get; set; }
public long ChannelId { get; set; }
public virtual Channel Channel { get; set; }
public long UserId { get; set; }
public virtual User User { get; set; }
public bool IsOwner { get; set; }
}
How to make this efficient and working? What's the way to handle all relations?
Thanks

You have defined a number of many-to-many relationships where 1-to-many would suffice:
User is tied to one Company
Channel is tied to one Company, can have many users
Company can have many users, can have many channels
public class User
{
[Key]
public int UserId { get; set; }
public virtual Channel Channel { get; set; }
}
public class Channel
{
[Key]
public int ChannelId { get; set; }
public virtual Company Company { get; set; }
public virtual ICollection<User> Users { get; set; } = new List<User>();
}
public class Company
{
[Key]
public int CompanyId { get; set; }
public virtual ICollection<Channel> Channels { get; set; } = new List<Channel>();
}
When mapped, the company mapping will have a HasMany(x => x.Channels).WithRequired(x => x.Company);
The channel mapping will have a HasMany(x => x.Users).WithOptional();
To get Users for a company you can go through Channels:
var companyUsers = context.Companies
.Where(c => c.CompanyId == companyId)
.SelectMany(c => c.Channels.SelectMany(ch => ch.Users))
.ToList();
That being a very basic example to get all users associated with a single company. When reading company and related channel/user info you can dive through the association to select and filter the details as desired.
Just as with DB design, it is usually advisable to keep entity relationships relatively normalized to avoid references to each other scattered everywhere. EF does a great job of building queries to pull data through the navigation properties where needed.
Edit: Ok, users can create a channel, potentially creating multiple channels and assuming from the earlier description multiple other users can be assigned to the channel. Channels are also potentially "owned" by one company.
Take 2:
public class User
{
[Key]
public int UserId { get; internal set; }
public virtual Company Company { get; internal set; } // optional
public virtual ICollection<ChannelUser> ChannelUsers { get; internal set; } = new List<ChannelUser>();
[NotMapped]
public ICollection<Channel> Channels
{
get { return ChannelUsers.Select(x => x.Channel).ToList(); }
}
[NotMapped]
public ICollection<Channel> OwnedChannels
{
get { return ChannelUsers.Where(x => x.IsOwned).Select(x => x.Channel).ToList(); }
}
}
public class Channel
{
[Key]
public int ChannelId { get; internal set; }
public virtual ICollection<ChannelUser> ChannelUsers { get; internal set; } = new List<ChannelUser>();
public virtual ICollection<ChannelCompany> ChannelCompanies { get; internal set; } = new List<ChannelCompany>();
[NotMapped]
public User OwnerUser
{
get { return ChannelUsers.SingleOrDefault(x => x.IsOwner)?.User; }
}
[NotMapped]
public User OwnerCompany
{
get { return ChannelCompanies.SingleOrDefault(x => x.IsOwner)?.Company; }
}
}
public class Company
{
[Key]
public int CompanyId { get; internal set; }
}
public class ChannelUser
{
public int ChannelId { get; internal set; }
public int UserId { get; internal set; }
public bool IsOwner { get; internal set; }
public virtual Channel Channel { get; internal set; }
public virtual User User { get; internal set; }
}
public class ChannelCompany
{
public int ChannelId { get; internal set; }
public int CompanyId { get; internal set; }
public bool IsOwner { get; internal set; }
public virtual Channel Channel { get; internal set; }
public virtual Company Company { get; internal set; }
}
This maps similar to your original with many-to-many relationships between Channel and User and Company. The concept of an "owner" would be on the joining tables. I added some unmapped helper properties to make it easier for code using the entities to navigate through the linking entities. Be warned though that these properties cannot be used in EF Linq expressions. For instance when writing Linq queries against the dbSets and navigation properties you will need to use the linking entity collections because EF won't be able to resolve the unmapped ones. EF6 & EF Core 3+ will throw exceptions if you try to use them in a query, EF Core 2 would generate a warning and auto-materialize the query into memory which is a potentially huge performance/memory sink.
The trouble with models like this is that they can get the job done, but will rely on your code logic to enforce that the rules around expected relationships between channels, users, and companies are enforced. For instance, expecting that every channel has 1, and only 1 owning user (if required) and 0 or 1 owning company. (if optional)
To do this, I would recommend using Actions (methods) on the entities to modify state rather than accessing setters/collections directly. For example, if you can create a channel for a user, have a CreateChannel() method on user with the required parameters:
public Channel CreateChannel(string name /* , other required fields */)
{
var channel = new Channel
{
Name = name,
//...
};
var channelUser new ChannelUser { Channel = channel, User = this, IsOwner = true });
ChannelUsers.Add(channelUser);
channel.ChannelUsers.Add(channelUser);
return channel;
}
This assumes that the DbContext that read the associated User entity is in-scope and alive when user.CreateChannel() is called, and SaveChanges() is called afterwards. For instance, somewhere in a controller action to create a Channel from data provided in the Post:
using (var context = new AppContext())
{
var user = context.Users.Single(x => x.UserId == userId);
var channel = user.CreateChannel(channelName /*, .... */);
context.SaveChanges();
// Potentially return view information for the newly created Channel...
}
Changing a channel owner between users (whether limited to user already associated to the channel or a new user) can be contained in a method on Channel to update the appropriate collections in one operation to ensure the IsOwner state is kept valid. This is where I will make setters internal to discourage attempting to mutate state with setters instead of using action methods.
Anyhow, this should hopefully give you a few things to think about. Ultimately look to narrow down the allowed relationships to the minimum viable connection points between the entities. Many-to-many relationships can complicate things in terms of enforcing valid combinations.

Related

I am not able to have one-to-many relationship in Entity Framework

I am following examples from the internet but it's not working. The database is getting created successfully, there is no error.
What I want to have is: one user can have multiple transactions, and a transaction can have references to two users. One of those is the user who did the transaction, the second is the user to whom transaction is done.
But what is happening is I am getting three foreign keys in the Users table, but none in the Transactions table.
See image below:
My classes
public class User
{
public int userId { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string CardNumber { get; set; }
public string Password { get; set; }
public int Balance { get; set; }
public string UserType { get; set; }
public string ProfileUrl { get; set; }
public IList<Transaction> Transactions { get; set; }
}
public class Transaction
{
public Transaction()
{
this.TranscationDateTime = DateTime.UtcNow;
}
public int TransactionId { get; set; }
public int Amount { get; set; }
public User FromUser { get; set; }
public User ToUser { get; set; }
public DateTime TranscationDateTime { get; set; }
}
public class DB: DbContext
{
public DB() : base("name=DBConnection")
{ }
public DbSet<User> Users { get; set; }
public DbSet<Transaction> Transactions { get; set; }
}
You need to make some modification to your code.
First of all, each navigation property needs to be marked as virtual, in order to allow Entity Framework to lazy loading, unless you want always eager load all your navigations (could be a choice, is up to you).
After that, each of your user has outgoing and incoming transactions, so for the User class:
public class User
{
public int userId { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string CardNumber { get; set; }
public string Password { get; set; }
public int Balance { get; set; }
public string UserType { get; set; }
public string ProfileUrl { get; set; }
public virtual IList<Transaction> IncomingTransactions { get; set; }
public virtual IList<Transaction> OutgoingTransactions { get; set; }
}
Let's make virtual navigation properties of Transaction class
public class Transaction
{
public Transaction()
{
this.TranscationDateTime = DateTime.UtcNow;
}
public int TransactionId { get; set; }
public int Amount { get; set; }
public virtual User FromUser { get; set; }
public virtual User ToUser { get; set; }
public DateTime TranscationDateTime { get; set; }
}
Last, but not least, let's inform your DbContext of how things are supposed to go:
public class MyContext : DbContext
{
public MyContext(string connectionString) : base(connectionString) { }
public DbSet<User> Users { get; set; }
public DbSet<Transaction> Transactions { get; set; }
protected override void OnModelCreating(DbModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<Transaction>()
.HasRequired<User>(t => t.FromUser)
.WithMany(u => u.OutgoingTransactions).WillCascadeOnDelete(false);
builder.Entity<Transaction>()
.HasRequired<User>(t => t.ToUser)
.WithMany(u => u.IncomingTransactions).WillCascadeOnDelete(false);
}
}
This should be enough for EF autodiscovery to make the right assumptions and create right database structure, that would be two FKs in Transaction table each of them to the primary key of Users table.
And voilĂ :
This happens because EF doesn't know that one of the FromUser and ToUser fields is supposed to match the collection Transactions - since you are not following the naming conventions. You have several options on how to resolve this situation:
If you only want to match Transactions collection with either FromUser or ToUser but not both, you can use [ForeignKey] and/or [InverseProperty] attributes to setup the database relation explicitly
If you want to use BOTH of them, then you would need to specify two collections in the User class - e.g. TransactionsFromUser and TransactionsToUser. You might still need to setup the relationships explicitly through the attributes though
What i want to have is one user can have multiple transaction but a transaction can have reference to two user.
Your current database model reflects this accuratly. I will explain why in the rest of my answer.
The User table can not hold the foreign keys to the Transactions table because one User can be associated with multiple Transactions. If the FK column was on the User table, it would need to hold more than one TransactionId.
Instead, the references to the Users are stored in the Transaction table. So every Transaction only has to store a single UserId per FK column.
Transaction.User_userId tells us that this Transaction is in the IList<Transaction> Transactions of the User with the stored User_userId.
To get this list of Transactions for a certain user, we query
SELECT *
FROM Transactions t
INNER JOIN Users u on t.User_userId = u.userId
WHERE u.userId = {theUserId}
The additional FKs ToUser_userId and FromUser_userId exists because they might reference different Users.
If the semantics of the IList<Transaction> Transactions is actually "all transactions that originated from this User", you could configure the ModelBuilder to use the FromUser_userId FK for this collection instead of creating the third FK User_userId. See the answer of Sergey.

Entity Framework Core not loading related data

We are developing a new application using ASP.NET Core and EF Core. We're on the latest stable release (v1.1.2). We are unable to load related data via navigation properties.
I am aware that lazy loading is not supported in EF Core but every post on the subject I have looked at suggests that we should be able to explicitly load related data using .Include(). However, this is not working for us and the related entities are always null when we load them in code.
We have two entities - 'Exchange' and 'Trade'. 'Exchange' has a foreign key to 'Trade' and contains a Virtual Trade called Request and another called Offer, thus:-
[Table("Exchange")]
public partial class Exchange : BaseEntity
{
public string Pending { get; set; }
[Display(Name = "Exchange Date"), DataType(DataType.Date)]
public DateTime DateOfExchange { get; set; }
public decimal EstimatedHours { get; set; }
public decimal ActualHours { get; set; }
public string Description { get; set; }
public string FollowUp { get; set; }
public string Status { get; set; }
[ForeignKey("User")]
[Required]
public int Broker_Fk { get; set; }
public virtual User Broker { get; set; }
public int Request_Fk { get; set; }
public virtual Trade Request { get; set; }
public int Offer_Fk { get; set; }
public virtual Trade Offer { get; set; }
I have a View Model that instantiates an 'Exchange' which I know has a related 'Request':-
_vm.Exchanges = _context.Exchange.Include(i => i.Request).Where(t => t.Request.User_Fk == user.Id || t.Offer.User_Fk == user.Id).ToList();
This returns an Exchange, which I am passing to and rendering in the View Model:-
#foreach (var item in Model.Exchanges)
{
<span>#item.Request.Name</span> <br />
}
The problem is that #item.Request is null, even though I have explicitly included it when loading the Exchange. I know that there really is a related entity in existence because one of the other properties on Exchange is its foreign key, which is populated.
What am I missing? Every example I have seen posted suggests that what I've done should work.
Your model attributes are messed up:
[Table("Exchange")]
public partial class Exchange : BaseEntity
{
//...
[ForeignKey("Broker")]
[Required]
public int Broker_Fk { get; set; }
public virtual User Broker { get; set; }
[ForeignKey("Request")]
public int Request_Fk { get; set; }
public virtual Trade Request { get; set; }
//...
}

Do I always have to include virtual properties when saving data in EF?

My user looks like this:
public class User
{
public User()
{
Subscribers = new List<SubscriberNumber>();
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string Username { get; set; }
[Required]
public virtual BusinessNumber BusinessNumber { get; set; }
public string BusinessName { get; set; }
public int SubscriberCount { get; set; }
public List<SubscriberNumber> Subscribers { get; set; }
}
The following call fails due to some undisclosed EntityValidationError:
var user = db.Users.First(s => s.Username == username);
user.BusinessName = "test";
db.SaveChanges();
But either opening up user.BusinessNumber in VS or using the following:
var user = db.Users.Include(s => s.BusinessNumber).First(s => s.Username == username);
gets SaveChanges() to work. Do I always have to include virtual properties when I'm updating my Users? This seems cumbersome...
The virtual on the properties allows EF to build a proxy. It is not essential to use virtual on regular properties for EF to read and write data. However Virtual is required on the Navigation properties.
By Default Context.Configuration.ValidateOnSaveEnabled = true;
EF will trigger validation on SaveChanges().
So in teh example where the Navigation property is Required (why?) The you must first populate it in the context and POCO. Placing the [required] on the foreign key property rather than the navigation property would be more common.
public class User
{
public User()
{
Subscribers = new List<SubscriberNumber>();
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string Username { get; set; }
[Required]
public virtual int BusinessId {get;set;}; // make the foreign key to BusinessNumber required if necessary
[ForeignKey("BusinessId")]
public virtual BusinessNumber BusinessNumber { get; set; } // this is a nav prop, since it isnt a simple base type
public string BusinessName { get; set; }
public int SubscriberCount { get; set; }
public List<SubscriberNumber> Subscribers { get; set; }
}

MVC EF code first creating model class

I'm new to MVC and EF code first. I'm in struggle to model a real-estate company DB model using EF code-first approach and I did some exercises as well as reading some online tutorials.
First thing I have a customers table that would be in relation with one or more properties he/she has registered as it's owner to sell or to rent, I was wondering if it is possible to have some sub classes inside a model class for registered properties as below:
public Property
{
public int PropertyID { get; set; }
public bool IsforSale { get; set; }
public bool IsforRent { get; set; }
public class Apartment{
public int ApartmentID { get; set; }
public int AptSqureMeter { get; set; }
. . .
. . .
}
public class Villa{
public int VillaID { get; set; }
public int VillaSqureMeter { get; set; }
. . .
. . .
}
and also other sub-classes for other types of properties
}
If the answer is Yes, then how should I declare the relations using data annotation or Fluent API, and then please help me how to update both Customers table and Property table with the customer information and property info at the same time?
thanks for your answer in advance.
As #Esteban already provided you with a pretty detailed answer on how to design your POCOs and manage the relationship between them, I will only focus on that part of your question:
how should I declare the relations using data annotation or Fluent API
First of all, you should know that certain model configurations can only be done using the fluent API, here's a non exhaustive list:
The precision of a DateTime property
The precision and scale of numeric properties
A String or Binary property as fixed-length
A String property as non-unicode
The on-delete behavior of relationships
Advanced mapping strategies
That said, I'm not telling you to use Fluent API instead of Data Annotation :-)
As you seem to work on an MVC application, you should keep in mind that Data Annotation attributes will be understood and processed by both by Entity Framework and by MVC for validation purposes. But MVC won't understand the Fluent API configuration!
Both your Villa and Apartment classes have similar properties, if they are the same but as it's type, you could create an enum for that.
public enum PropertyType {
Apartment = 1,
Villa
}
public class Property {
public int PropertyID { get; set; }
public bool IsforSale { get; set; }
public bool IsforRent { get; set; }
public PropertyType PropertyType { get; set; }
public int SquareMeter { get; set; }
}
This way of modelating objects is refered as plain old clr object or POCO for short.
Assume this model:
public class User {
public int UserId { get; set; }
public string Username { get; set; }
public virtual List<Role> Roles { get; set; }
}
public class Role {
public int RoleId { get; set; }
public string Name { get; set; }
public virtual List<User> Users { get; set; }
}
Creating relations with fluent api:
Mapping many to many
On your OnModelCreating method (you'll get this virtual method when deriving from DbContext):
protected override void OnModelCreating(DbModelBuilder builder) {
// Map models/table
builder.Entity<User>().ToTable("Users");
builder.Entity<Role>().ToTable("Roles");
// Map properties/columns
builder.Entity<User>().Property(q => q.UserId).HasColumnName("UserId");
builder.Entity<User>().Property(q => q.Username).HasColumnName("Username");
builder.Entity<Role>().Property(q => q.RoleId).HasColumnName("RoleId");
builder.Entity<Role>().Property(q => q.Name).HasColumnName("Name");
// Map primary keys
builder.Entity<User>().HasKey(q => q.UserId);
builder.Entity<Role>().HasKey(q => q.RoleId);
// Map foreign keys/navigation properties
// in this case is a many to many relationship
modelBuilder.Entity<User>()
.HasMany(q => q.Roles)
.WithMany(q => q.Users)
.Map(
q => {
q.ToTable("UserRoles");
q.MapLeftKey("UserId");
q.MapRightKey("RoleId");
});
Mapping different types of relationships with fluent api:
One to zero or one:
Given this model:
public class MenuItem {
public int MenuItemId { get; set; }
public string Name { get; set; }
public int? ParentMenuItemId { get; set; }
public MenuItem ParentMenuItem { get; set; }
}
And you want to express this relationship, you could do this inside your OnModelCreating method:
builder.Entity<MenuItem>()
.HasOptional(q => q.ParentMenuItem)
.WithMany()
.HasForeignKey(q => q.ParentMenuItemId);
One to many
Given this model:
public class Country {
public int CountryId { get; set; }
public string Name { get; set; }
public virtual List<Province> Provinces { get; set; }
}
public class Province {
public int ProvinceId { get; set; }
public string Name { get; set; }
public int CountryId { get; set; }
public Country Country { get; set; }
}
You now might want to express this almost obvious relationship. You could to as follows:
builder.Entity<Province>()
.HasRequired(q => q.Country)
.WithMany(q => q.Provinces)
.HasForeignKey(q => q.CountryId);
Here are two useful links from MSDN for further info:
Configuring Relationships with the Fluent API.
Code First Relationships Fluent API.
EDIT:
I forgot to mention how to create a many to many relationship with additional properties, in this case EF will NOT handle the creation of the join table.
Given this model:
public class User {
public int UserId { get; set; }
public string Username { get; set; }
public virtual List<Role> Roles { get; set; }
pubilc virtual List<UserEmail> UserEmails { get; set; }
}
pubilc class Email {
public int EmailId { get; set; }
public string Address { get; set; }
public List<UserEmail> UserEmails { get; set; }
}
public class UserEmail {
public int UserId { get; set; }
public int EmailId { get; set; }
public bool IsPrimary { get; set; }
public User User { get; set; }
public Email Email { get; set; }
}
Now that we've added a new property into our join table ef will not handle this new table.
We can achieve this using the fluent api in this case:
builder.Entity<UserEmail>()
.HasKey( q => new {
q.UserId, q.EmailId
});
builder.Entity<UserEmail>()
.HasRequired(q => q.User)
.WithMany(q => q.UserEmails)
.HasForeignKey(q => q.EmailId);
builder.Entity<UserEmail>()
.HasRequired(q => q.Email)
.WithMany(q => q.UserEmails)
.HasForeignKey(q => q.UserId);

M:M Mapping - EF 4.3 CodeFirst (Existing Database)

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