Connecting two context models in multiple ways in asp.net code first - asp.net-mvc

I'm sorry for the title but I didn't know a better way to express this in a short description.
Basically what I'm thinking, which I'm not ever sure if its possible or if there is a better way to to it, is the following:
I have a Project model, which belongs to a Company model, and a User model that should be linked to the Project in different ways.
So I was thinking of doing this:
public class Project
{
[Key]
[Required]
public Guid Id { get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
[Required]
[DataType(DataType.DateTime)]
public DateTime StartDate { get; set; }
[DataType(DataType.DateTime)]
public DateTime? EndDate { get; set; }
public virtual List<User> Clients { get; set; }
public virtual List<User> Employees { get; set; }
public virtual User Manager { get; set; }
public virtual List<User> ProjectLeaders { get; set; }
public virtual Company Company { get; set; }
}
So the project has to have employees, a manager, project leaders and clients, all of those vary by project and they are all users in the system.
I would also like to point out that I am using asp.net's identity membership system
The part that I'm not sure of is if this would even work out.
If it will work, how is it interpreted in the database side?
If not, could you guys point out why is this a bad idea and how it could be done properly?
Thank you very much!

As fer I understand you need a relation between Employee/user and project/Company.If I am not wrong.You can make one to many relation between them.
In a project or in a company can have multiple employees and at a time a employee can work for a company only.
So you can design your entities following way
So your project Entity means that It can have multiple employee
public class Project
{
[Key]
[Required]
public Guid Id { get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
[Required]
[DataType(DataType.DateTime)]
public DateTime StartDate { get; set; }
[DataType(DataType.DateTime)]
public DateTime? EndDate { get; set; }
public virtual List<User> Employees { get; set; }
}
And here your User Entity means that a user can work for a company at a time.
public class User
{
[Key]
[Required]
public Guid Id { get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
.................................
.................................
//ProjectId will be your foreign key
public int ProjectId { get; set; }
public virtual Project Project { get; set; }
}
Now Entity framework will make a one to many relation between them.
Note : and you can make many to many relation also if you want.It depends on you and your desire functionalities.

The best option to fix the problem was to use FluentAPI to properly connect the models.
Here is how the models should look after fix:
public class Project
{
[Key]
[Required]
public string Id{ get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
[Required]
[DataType(DataType.DateTime)]
public DateTime StartDate { get; set; }
[DataType(DataType.DateTime)]
public DateTime? EndDate { get; set; }
public virtual ICollection<User> Clients { get; set; }
public virtual ICollection<User> Employees { get; set; }
public virtual ICollection<User> ProjectLeaders { get; set; }
public virtual User ProjectManager { get; set; }
}
public class User : IdentityUser
{
public string Name { get; set; }
public virtual List<Project> ProjectsAsClient { get; set; }
public virtual List<Project> ProjectsAsEmployee { get; set; }
public virtual List<Project> ProjectsAsProjectLeader { get; set; }
public virtual Project ProjectAsManager { get; set; }
}
and on Context:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>()
.HasMany(u => u.ProjectsAsClient)
.WithMany(t => t.Clients)
.Map(x =>
{
x.MapLeftKey("UserId");
x.MapRightKey("ProjectId");
x.ToTable("ProjectClients");
});
modelBuilder.Entity<User>()
.HasMany(u => u.ProjectsAsEmployee)
.WithMany(t => t.Employees)
.Map(x =>
{
x.MapLeftKey("UserId");
x.MapRightKey("ProjectId");
x.ToTable("ProjectEmployees");
});
modelBuilder.Entity<User>()
.HasMany(u => u.ProjectsAsProjectLeader)
.WithMany(t => t.ProjectLeaders)
.Map(x =>
{
x.MapLeftKey("UserId");
x.MapRightKey("ProjectId");
x.ToTable("ProjectLeaders");
});
}

Related

Renaming default table names in asp.net mvc project without breaking foreign keys

I Created a new MVC 5 project whenever i try to rename the table names as described in this question
Change table names using the new Identity system
It always breaks the foreign key relationships in the Logins, Claims, Roles tables.
I have tried to override the OnModelCreating method but in vein here is my code
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//base.OnModelCreating(modelBuilder);
if (modelBuilder == null)
{
throw new ArgumentNullException("modelBuilder");
}
modelBuilder.Entity<App>().HasKey(m => new { m.AppId, m.FacebookId });
modelBuilder.Entity<IdentityUser>().ToTable("Admins");
modelBuilder.Entity<IdentityUser>().
Property(p => p.Id).HasColumnName("AdminId");
modelBuilder.Entity<Admin>()
.ToTable("Admins")
.Property(p => p.Id).HasColumnName("AdminId");
modelBuilder.Entity<IdentityUserLogin>().ToTable("Logins")
.HasKey(m => new { m.ProviderKey, m.UserId, m.LoginProvider })
.Property(m => m.UserId)
.HasColumnName("AdminId");
modelBuilder.Entity<IdentityUserRole>().ToTable("AdminRoles")
.HasKey(m => new { m.RoleId, m.UserId })
.Property(m => m.RoleId)
.HasColumnName("AdminRoleId");
modelBuilder.Entity<IdentityUserRole>().Property(m => m.UserId)
.HasColumnName("AdminId");
//modelBuilder.Entity<IdentityUserRole>().HasRequired(m => m.UserId);
//modelBuilder.Entity<IdentityUserLogin>().HasRequired(m => m.UserId);
modelBuilder.Entity<IdentityUserClaim>().ToTable("Claims")
.HasKey(m=> m.Id)
.Property(m => m.Id)
.HasColumnName("ClaimId");
modelBuilder.Entity<IdentityRole>().ToTable("Roles")
.HasKey(m => m.Id).Property(m => m.Id).HasColumnName("RoleId");
}
where the "Admin" Class is my name for the ApplicationUser Default class plus my own implementation of it
public class Admin : IdentityUser
{
[Required]
public virtual List<App> Apps { get; set; }
public bool? IsPremium { get; set; }
[DataType(DataType.Date)]
public DateTime? LastPublishDateTime { get; set; }
}
here are my other domain classes
public class App
{
[Key]
[Column("AppId", Order = 1)]
public virtual int AppId { get; set; }
[Required]
[Key]
[Column("FacebookId", Order = 2)]
public virtual string FacebookId { get; set; }
[Required]
public virtual string Secret { get; set; }
public virtual List<User> Users { get; set; }
public virtual List<Post> Posts { get; set; }
[Required]
public virtual Admin Admin { get; set; }
}
public class Post
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public virtual int PostId { get; set; }
public virtual string Title { get; set; }
public virtual string Content { get; set; }
public virtual string Link { get; set; }
public virtual string Image { get; set; }
public virtual bool IsSpecial { get; set; }
[Required]
public virtual App App { get; set; }
[Required]
public virtual DateTime? PublishDate { get; set; }
}
public class User
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public virtual int UserId { get; set; }
[MaxLength(500)]
public virtual string FacebookId { get; set; }
[MaxLength(500)]
public virtual string Token { get; set; }
[Required]
public virtual App App { get; set; }
}

Entity Framework Many to Many Cascade Delete Issue

Having a strange issue working on a code first EF project.
I have the following entities:
public class Booking
{
public Guid BookingId { get; set; }
public virtual List<AccountingDocumentItem> AccountingDocumentItems { get; set; }
}
public class AccountingDocumentItem
{
public Guid AccountingDocumentItemId { get; set; }
public virtual List<Employee> Employees { get; set; }
public virtual List<Booking> Bookings { get; set; }
}
public class Employee
{
public Guid EmployeeId { get; set; }
public string Name { get; set; }
public virtual List<AccountingDocumentItem> AccountingDocumentItems { get; set; }
}
As you can see, there is meant to be many-to-many relationship between AccountingDocumentItem and both Bookings and Employees. When configuring my AccountingDocumentItem I use the following:
public AccountingDocumentItemConfiguration()
{
HasMany(x => x.Employees);
HasMany(x => x.Bookings);
}
What is strange is that this works perfectly for Employees. I get a AccountingDocumentItemEmployees table created. But for Bookings I get the following error:
"Introducing FOREIGN KEY constraint 'FK_dbo.AccountingDocumentItemBookings_dbo.Bookings_Booking_BookingId' on table 'AccountingDocumentItemBookings' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints."
Now I've tried to do this along the lines of below code:
HasMany(x => x.Bookings).WithMany(b => b.AccountingDocumentItems)...
But I only get the option to do a Map using the above line, no option to do a WillCascadeOnDelete(false).
Can someone point out what I'm doing wrong, because comparing it to how I handle Employees I can't see any difference.
EDIT:
My original post abbreviated the entities, which is probably where the problem is arising. Here is the full entity:
public class AccountingDocument
{
public Guid AccountingDocumentId { get; set; }
public Guid SiteId { get; set; }
public virtual Site Site { get; set; }
public Guid? ClientId { get; set; }
public virtual Client Client { get; set; }
public Guid? SupplierId { get; set; }
public virtual Supplier Supplier { get; set; }
public string DocumentNumber { get; set; }
public string Reference { get; set; }
public string Description { get; set; }
public string Notes { get; set; }
public Guid LinkedAccountingDocumentId { get; set; }
public virtual AccountingDocument LinkedAccountingDocument { get; set; }
public byte AccountingDocumentTypeId { get; set; }
public DateTime CreationDate { get; set; }
public DateTime DocumentDate { get; set; }
public decimal Total { get; set; }
public Guid UserId { get; set; }
public virtual User User { get; set; }
public string Room { get; set; }
public virtual List<AccountingDocumentItem> AccountingDocumentItems { get; set; }
}
public class AccountingDocumentItem
{
public Guid AccountingDocumentItemId { get; set; }
public Guid AccountingDocumentId { get; set; }
public virtual AccountingDocument AccountingDocument { get; set; }
public string Description { get; set; }
public Guid TaxId { get; set; }
public virtual Tax Tax { get; set; }
public decimal Quantity { get; set; }
public string Unit { get; set; }
public decimal Cost { get; set; }
public decimal SellInclusive { get; set; }
public decimal SellExclusive { get; set; }
public decimal DiscountPercentage { get; set; }
public decimal TotalInclusive { get; set; }
public decimal TotalExclusive { get; set; }
public decimal CommissionInclusive { get; set; }
public decimal CommissionExclusive { get; set; }
public int LoyaltyPoints { get; set; }
public bool IsSeries { get; set; }
public byte ItemType { get; set; }
public Guid? ServiceId { get; set; }
public virtual Service Service { get; set; }
public Guid? ProductId { get; set; }
public virtual Product Product { get; set; }
public Guid? VoucherId { get; set; }
public virtual Voucher Voucher { get; set; }
public int SortOrder { get; set; }
public Guid? SourceId { get; set; }
public virtual Source Source { get; set; }
public Guid? CostCentreId { get; set; }
public virtual CostCentre CostCentre { get; set; }
public Guid? ClientId { get; set; }
public virtual Client Client { get; set; }
public Guid PackageGroupId { get; set; }
public Guid PackageServiceId { get; set; }
public virtual List<Employee> Employees { get; set; }
public virtual List<Booking> Bookings { get; set; }
public virtual List<MedicalDiagnosis> MedicalDiagnoses { get; set; }
}
public class Booking
{
public Guid BookingId { get; set; }
public Guid SiteId { get; set; }
public Site Site { get; set; }
public Guid? ClientId { get; set; }
public Client Client { get; set; }
public Guid BookingStateId { get; set; }
public BookingState BookingState { get; set; }
public virtual List<AccountingDocumentItem> AccountingDocumentItems { get; set; }
}
And my configuration:
public class AccountingDocumentConfiguration : EntityTypeConfiguration<AccountingDocument>
{
public AccountingDocumentConfiguration()
{
Property(x => x.Reference).HasMaxLength(200);
HasRequired(x => x.Site);
Property(x => x.DocumentNumber).IsRequired().HasMaxLength(100);
Property(x => x.Reference).HasMaxLength(200);
Property(x => x.Description).HasMaxLength(500);
Property(x => x.Notes).HasMaxLength(500);
HasOptional(x => x.LinkedAccountingDocument);
Property(x => x.AccountingDocumentTypeId).IsRequired();
Property(x => x.CreationDate).IsRequired();
Property(x => x.DocumentDate).IsRequired();
Property(x => x.Total).IsRequired();
Property(x => x.Room).HasMaxLength(50);
}
}
public class AccountingDocumentItemConfiguration : EntityTypeConfiguration<AccountingDocumentItem>
{
public AccountingDocumentItemConfiguration()
{
Property(x => x.Description).IsRequired().HasMaxLength(200);
HasMany(x => x.Employees);
HasMany(x => x.Bookings);
HasMany(x => x.MedicalDiagnoses);
Property(x => x.Unit).HasMaxLength(50);
}
}
Even with the added text above it's working for me, once I comment out the added nav properties that aren't fully defined above. The FK error means that there might be a race condition if you happen to delete (See this article), but with whats here I can't tell. Do you need to have cascading deletes on your database? If not, you could just turn it off - I realize it's a pretty broad stroke on a minor problem though.
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
If this is not an option - it's something else that you haven't included. Do you have mappings for the Bookings table? It looks like Bookings have a required Site - is it possible that deleting a site, could trigger a delete in a bunch of other things? It looks like Site could do something like this Site -> Account Document -> Accounting Document item.. Site -> Booking possibly?
Here's another SO question that could possibly be related.

Entityframework port from model first to code first

I am still on my quest to port from a Model First to Code First implementation of EntityFramework. I have made significant progress, with the help of Eranga. I have run into another snag, and I just cant explain what is hapening. I have two Entity objects Topic and Course
A Topic can have one Course that is required
A Course can have 0 or more topics
when i execute the following linq it generates wierd SQL
var topics = from o in db.Topics where o.ParentTopic == null &&
o.Course.Id == c.Id select o;
The SQL generated is
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
[Extent1].[ShortDescription] AS [ShortDescription],
[Extent1].[LongDescription] AS [LongDescription],
[Extent1].[Property] AS [Property],
[Extent1].[Difficulty] AS [Difficulty],
[Extent1].[Weight] AS [Weight],
[Extent1].[Course_Id] AS [Course_Id],
[Extent1].[ParentTopic_Id] AS [ParentTopic_Id],
[Extent1].[Course_Id1] AS [Course_Id1]
FROM [dbo].[Topics] AS [Extent1]
WHERE ([Extent1].[ParentTopic_Id] IS NULL) AND ([Extent1].[Course_Id] = #p__linq__0)
Notice that there is an added field called Course_Id1 that is not in my object and not declared as a foreign key. I thought that in OnModelCreating() I had specified the parent child relationship correctly from both sides (I would have thought you only needed to do it from either side), but i cant get EntityFramework not to generate the extra field that obviously does not exist in the database. Remember my database was originally created using a ModelFirst approach.
Can anyone explain where the extra field is comming from????
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Topic
modelBuilder.Entity<Topic>()
.HasRequired(m => m.Course)
.WithMany(m=>m.Topics)
.HasForeignKey(m => m.Course_Id);
modelBuilder.Entity<Topic>()
.HasOptional(m => m.ParentTopic)
.WithMany(m => m.ChildTopics)
.HasForeignKey(m => m.ParentTopic_Id);
//////// lots of code removed for brevity. //////
modelBuilder.Entity<Course>()
.HasMany(m=>m.Topics)
.WithRequired(m => m.Course)
.HasForeignKey(m => m.Course_Id);
}
public partial class Topic
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public string ShortDescription { get; set; }
public string LongDescription { get; set; }
public string Property { get; set; }
public double? Difficulty { get; set; }
public double? Weight { get; set; }
[JsonIgnore]
public virtual Course Course { get; set; }
public int Course_Id { get; set; }
[JsonIgnore]
public virtual ICollection<Question> Questions { get; set; }
[JsonIgnore]
public virtual ICollection<Topic> ChildTopics { get; set; }
[JsonIgnore]
public virtual Topic ParentTopic { get; set; }
public int? ParentTopic_Id { get; set; }
[JsonIgnore]
public virtual ICollection<RTIQueueEntryData> RTIQueueEntryData { get; set; }
[JsonIgnore]
public virtual ICollection<Intervention> Interventions { get; set; }
[JsonIgnore]
public virtual ICollection<RtiStudentGroup> RtiStudentGroups { get; set; }
}
public partial class Course
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
public string Version { get; set; }
public string Year { get; set; }
public string ImportedId { get; set; }
[Required]
public string LocalCourseNumber { get; set; }
[Required]
public string NCESCourseNumber { get; set; }
[Required]
public string StateCourseNumber { get; set; }
public int? Grade { get; set; }
[JsonIgnore]
public virtual ICollection<Topic> PerformanceIndicators { get; set; }
[JsonIgnore]
public virtual Department Department { get; set; }
public int DepartmentId { get; set; }
[JsonIgnore]
public virtual ICollection<StudentGroup> StudentGroups { get; set; }
[JsonIgnore]
public virtual ICollection<CutPointTemplate> CutPointTemplates { get; set; }
[JsonIgnore]
public virtual School School { get; set; }
public int School_Id { get; set; }
[JsonIgnore]
public virtual ICollection<Staff> RTIStaff { get; set; }
[JsonIgnore]
public virtual ICollection<Topic> Topics { get; set; }
}
You have another relationship between Course and Topic created by convention due to this navigation property:
public virtual ICollection<Topic> PerformanceIndicators { get; set; }
EF will put an (invisible, not exposed) end of the relationship into the Topic class. By default the relationship is one-to-many. Hence you get an additional foreign key property in the Topics table (= Course_Id1).

Use MVC 3 and Entity Framework, how do I map a different instance of the same class to 3 different collection properties?

So I created the following related Classes and I'm trying to do Code-First approach. I want the Quote class to reference 3 instances of the User class by 3 different navigable property names, but when I do DBInitializer to populate and create the DB, the Quote table has 6 columns instead of the expected 3 columns, of which 3 are always null. The navigable properties point to those 3 null columns, so whenever I point to Quote.Manager or one of the other 3 properties, it returns null instead of the actual manager. How can I fix this?
Quote Class (I left a little off, but you get the point):
using System.Web;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace QuoteManager.Models
{
public class Quote
{
public int QuoteID { get; set; }
public virtual int StateID { get; set; }
public virtual State State { get; set; }
public virtual int CreatorID { get; set; }
public virtual User Creator { get; set; }
public virtual int AgentID { get; set; }
public virtual User Agent { get; set; }
public virtual int ManagerID { get; set; }
public virtual User Manager { get; set; }
}
}
User class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace QuoteManager.Models
{
public class User
{
public User()
{
this.Quotes = new HashSet<Quote>();
this.CreatedQuotes = new HashSet<Quote>();
this.ManagedQuotes = new HashSet<Quote>();
}
public int UserID { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual string Phone { get; set; }
public virtual string Email { get; set; }
public virtual ICollection<Quote> Quotes { get; set; }
public virtual ICollection<Quote> CreatedQuotes { get; set; }
public virtual ICollection<Quote> ManagedQuotes { get; set; }
public virtual ICollection<Note> Notes { get; set; }
}
}
Use the InverseProperty attribute to specify the other property participating in the relationship
public class Quote
{
public int QuoteID { get; set; }
public virtual int StateID { get; set; }
public virtual State State { get; set; }
public virtual int CreatorID { get; set; }
[InverseProperty("CreatedQuotes")]
public virtual User Creator { get; set; }
public virtual int AgentID { get; set; }
public virtual User Agent { get; set; }
public virtual int ManagerID { get; set; }
[InverseProperty("ManagedQuotes")]
public virtual User Manager { get; set; }
}
public class User
{
public User()
{
this.Quotes = new HashSet<Quote>();
this.CreatedQuotes = new HashSet<Quote>();
this.ManagedQuotes = new HashSet<Quote>();
}
public int UserID { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual string Phone { get; set; }
public virtual string Email { get; set; }
public virtual ICollection<Quote> Quotes { get; set; }
[InverseProperty("Creator")]
public virtual ICollection<Quote> CreatedQuotes { get; set; }
[InverseProperty("Manager")]
public virtual ICollection<Quote> ManagedQuotes { get; set; }
public virtual ICollection<Note> Notes { get; set; }
}
Similarly map the other relations.
Add the attribute [ForeignKey("Creator")] to the CreatorID and so on for the other 2 property pairs.
FINAL SOLUTION
Thanks to your reference to InverseProperty I found an amazing article that covers exactly what I wanted to accomplish using fluent API. This article was written in January, but I'm pretty sure CTP5 is now officially part of the MVC 3 and EF core.
Associations in EF Code First CTP5
Okay...I'm going to document what I found to work great! I hate it when people leave partial answers, so here we go.
There is a little redundancy here, but it works. My Quote Class looks like this:
[ForeignKey("Creator")]
public virtual int CreatorID { get; set; }
[InverseProperty("CreatedQuotes")]
public virtual User Creator { get; set; }
[ForeignKey("Agent")]
public virtual int AgentID { get; set; }
[InverseProperty("OwnedQuotes")]
public virtual User Agent { get; set; }
[ForeignKey("Manager")]
public virtual int ManagerID { get; set; }
[InverseProperty("ManagedQuotes")]
public virtual User Manager { get; set; }
Then my User class looks like this:
public virtual ICollection<Quote> CreatedQuotes { get; set; }
public virtual ICollection<Quote> OwnedQuotes { get; set; }
public virtual ICollection<Quote> ManagedQuotes { get; set; }
Finally, my DBContext class looks like this:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Quote>()
.HasRequired(a => a.Manager)
.WithMany()
.HasForeignKey(u => u.ManagerID);
modelBuilder.Entity<Quote>()
.HasRequired(a => a.Agent)
.WithMany()
.HasForeignKey(u => u.AgentID).WillCascadeOnDelete(false);
modelBuilder.Entity<Quote>()
.HasRequired(a => a.Manager)
.WithMany()
.HasForeignKey(u => u.ManagerID).WillCascadeOnDelete(false);
}
You can see the redundancy in the ForeignKey annotation in the Quote class and the Fluent API mapping in the DbContext class, but it's not hurting anything. I could probably do away with the annotations in the Quote class, but the Fluent API is necessary to set the cascading rule to false to prevent foreign key conflicts.
I have been able to navigate both directions with no problems and exactly as expected.
Thanks for all your help!

Mapping suggestion for a possibly shared foreign key (value object in entity) in Entity Framework 4.1?

I have a Project entity and an Rfi entity. The project entity contains a list of TeamMembers. Project is a navigation property in the Rfi entity. In the Rfi entity there is a RecipientId. This Id represents a person from the TeamMembers collection. So imagine, on a web page, we have a drop down box named Recipient. The list includes all team members of the Project. The user will select a Contact from that list. The Id of that contact will be saved in the RecipientsId property. When the page is reloaded we will select the Id of that user in the drop down based off the value in the RecipeintsId property. What is the best way to map this in EF 4.1 using the fluent API?
public class Project : BaseEntity
{
public string ProjectNumber { get; set; }
public string Description { get; set; }
public string CreatedBy { get; set; }
public string ModifiedBy { get; set; }
public string Currency { get; set; }
#region Navigation Properties
public Guid AddressId { get; set; }
public virtual Address Address { get; set; }
public Guid CompanyCodeId { get; set; }
public virtual CompanyCode CompanyCode { get; set; }
public virtual ICollection<Contact> TeamMembers { get; set; }
#endregion
}
public class Rfi : Document
{
public string Number { get; set; }
public string Subject { get; set; }
public string SubcontractorRfiReference { get; set; }
public string SpecificationSection { get; set; }
public RfiStatus RfiStatus { get; set; }
public Guid RecipientId { get; set; }
#region Navigation Properties
public Guid ProjectId { get; set; }
public Project Project { get; set; }
#endregion
}
As I understand it your problem is mapping between Rfi and Contect - Project doesn't have any role in your Recipient functionality from the database perspective.
You need either Recipient navigation property in Rfi or Rfis navigation property in Contact. EF code first needs navigation property on at least one side of the relation.
So you can use something like:
public class Rfi : Document
{
public string Number { get; set; }
public string Subject { get; set; }
public string SubcontractorRfiReference { get; set; }
public string SpecificationSection { get; set; }
public RfiStatus RfiStatus { get; set; }
#region Navigation Properties
public Guid RecipientId { get; set; }
public Contact Recipient { get; set; }
public Guid ProjectId { get; set; }
public Project Project { get; set; }
#endregion
}
And map:
modelBuilder.Entity<Rfi>()
.HasRequired(r => r.Recipient)
.WithMany()
.HasForeignKey(r => r.RecipientId);

Resources