Following the example in this question: How to create a many-to-many mapping in Entity Framework? I would like to have a table mapping where I can add or remove many-to-many relationships without having to go through the Media or Contract entities.
Essentially, I would like to have:
public class Media // One entity table
{
public int Id { get; set; }
public string Name { get; set; }
public bool Enabled { get; set; }
public virtual ICollection<Contract> Contracts { get; set; }
}
public class Contract // Second entity table
{
public int Id { get; set; }
public string Code { get; set }
public virtual ICollection<Media> Medias { get; set; }
}
public class ContractMedia // Association table implemented as entity
{
public Media Media { get; set; }
public int MediaId { get; set; }
public Contract Contract { get; set; }
public int ContractId { get; set; }
}
Is it possible to configure this scenario using the FluentAPI?
afaik not with the ContractMedia entity, but you can:
public class Media // One entity table
{
public int Id { get; set; }
public string Name { get; set; }
public bool Enabled { get; set; }
public virtual ICollection<ContractMedia> Contracts { get; set; }
}
public class Contract // Second entity table
{
public int Id { get; set; }
public string Code { get; set }
public virtual ICollection<ContractMedia> Medias { get; set; }
}
public class ContractMedia // Association table implemented as entity
{
public Media Media { get; set; }
public int MediaId { get; set; }
public Contract Contract { get; set; }
public int ContractId { get; set; }
}
or
public class Media // One entity table
{
public int Id { get; set; }
public string Name { get; set; }
public bool Enabled { get; set; }
public virtual ICollection<Contract> Contracts { get; set; }
}
public class Contract // Second entity table
{
public int Id { get; set; }
public string Code { get; set }
public virtual ICollection<Media> Medias { get; set; }
}
that will lead to the creation of a non mapped association table in the database.
Related
I have a question regarding Many to Many tables using EF Core.
Assume I have the below situation:
public class Book
{
public int BookId { get; set; }
public string Title { get; set; }
public Author Author { get; set; }
public ICollection<BookCategory> BookCategories { get; set; }
}
public class Category
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public ICollection<BookCategory> BookCategories { get; set; }
}
public class BookCategory
{
public int BookId { get; set; }
public Book Book { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
}
Now, assume that I want to have another table called "Contracts" which should be a child of "BookCategory".
How can I create this relationship?
This question already has answers here:
EF Core returns null relations until direct access
(2 answers)
Closed 4 years ago.
So I have 3 classes:
public class OwnerDto
{
public int Id { get; set; }
public string Name { get; set; }
public string EmailAddress { get; set; }
}
public class SitterDto
{
public int Id { get; set; }
public string Name { get; set; }
public string EmailAddress { get; set; }
}
public class ReviewDto
{
public int Id { get; set; }
public int Rating { get; set; }
//[ForeignKey("OwnerId")]
public OwnerDto Owner { get; set; }
//[ForeignKey("SitterId")]
public SitterDto Sitter { get; set; }
}
But I can't figure out how to do the proper modelBuilder. Everything I tried fails :( I am learning so bear with me.
My closest attempt was this:
modelBuilder.Entity<ReviewDto>()
.HasOne(t => t.Owner).WithMany().HasForeignKey("OwnerId");
Basically Owner and Sitter are always null :( Should i keep the [ForeignKey()] stuff or should i use a different extension method?
Declare all classes with navigation properties to each other. Mark one of the tables (the dependent table) with the ForeignKey attribute on its Primary Key.
EF infers one-to-many from this:
public class OwnerDto
{
public int Id { get; set; }
public string Name { get; set; }
public string EmailAddress { get; set; }
public ICollection<ReviewDto> Reviewers{ get; set; }
public ICollection<SitterDto> Sitters{ get; set; }
}
public class SitterDto
{
public int Id { get; set; }
public string Name { get; set; }
public string EmailAddress { get; set; }
public int OwnerId{ get; set; }
[ForeignKey("OwnerId")]
public OwnerDto Owner { get; set; }
}
public class ReviewDto
{
public int Id { get; set; }
public int Rating { get; set; }
public int OwnerId{ get; set; }
[ForeignKey("OwnerId")]
public OwnerDto Owner { get; set; }
}
and EF infers one-to-one from this:
public class OwnerDto
{
...
public ReviewDto Review{ get; set; }
...
}
public class ReviewDto
{
[ForeignKey("Owner")]
public int OwnerId { get; set; }
public OwnerDto Owner{ get; set; }
...
}
You need to refer Eager Loading in this scenario, You can use the Include method to specify related data to be includethe d in query results.
var query = from review in context.Review.Include(o => o.Owner).Include(s=>s.Sitter) select review;
I want to store below entities into one single table. I am getting response from REST apis which is hierarchical JSON but i need to take that JSON structure and Store as flat structure into sql server database. I am using new .net framework and EF 7.
CampaignID (id)
CampaignTitle (settings.title)
CampaignType (type)
Status (status)
EmailsSent (emails_sent)
SendTime (send_time)
RecipientsListId (recipients.list_id)
RptSmryOpens report_summary.opens
RptSmryUniqOpens report_summary.unique_opens
RptSmryOpenRate report_summary.open_rate
RptSmryClicks report_summary.clicks
RptSmrySubsClicks report_summary.subscriber_clicks
RptSmryClickRate report_summary.click_rate
public class Campaign
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty(#"settings")]
public Settings Settings { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("report_summary")]
public ReportSummary ReportSummary { get; set; }
}
public class Settings
{
[JsonProperty("title")]
public string Title { get; set; }
}
public class ReportSummary
{
[JsonProperty("opens")]
public int Opens { get; set; }
[JsonProperty("unique_opens")]
public int UniqueOpens { get; set; }
[JsonProperty("open_rate")]
public double OpenRate { get; set; }
[JsonProperty("clicks")]
public int Clicks { get; set; }
[JsonProperty("subscriber_clicks")]
public int SubscriberClicks { get; set; }
[JsonProperty("click_rate")]
public double ClickRate { get; set; }
}
My EF Code First model for some reason is not in sync with the db. I'm getting this error:
{"Invalid column name 'Type_Id1'."}
The field is actually called 'Type_Id' so I'm not sure from where that 1 comes up. I have the table column called as Type_Id and also I've added a Type_Id in my type entity model.
Why might I be getting that error message, plus why I'm getting 1 at the end of the name?
Update
My Task class:
public class Task
{
public Task()
{
Language = 1;
Grades = new HashSet<Grade>();
Categories = new HashSet<Category>();
Subjects = new HashSet<Subject>();
Rooms = new Collection<Room>();
Tools = new Collection<Tool>();
}
[Key]
public int Id { get; set; }
public string Description { get; set; }
public virtual TaskType Type { get; set; }
public string Rules { get; set; }
[Required]
[StringLength(200), MinLength(1)]
public string Name { get; set; }
public int PreperationTime { get; set; }
public int InstructionTime { get; set; }
public int TaskTime { get; set; }
public int Type_Id { get; set; }
public string VideoLink { get; set; }
[Required]
public int Language { get; set; }
public int? MinimumParticipants { get; set; }
public int? MaximumParticipants { get; set; }
public int? Rating { get; set; }
[Required]
public string CreatedBy { get; set; }
public virtual ICollection<Grade> Grades { get; set; }
public virtual ICollection<Category> Categories { get; set; }
public virtual ICollection<Subject> Subjects { get; set; }
public virtual ICollection<Room> Rooms { get; set; }
public virtual ICollection<Tool> Tools { get; set; }
}
DBContext class:
public ApplicationDbContext() : base("DefaultConnection", false)
{
}
public DbSet<Task> Tasks { get; set; }
public DbSet<TaskType> TaskTypes { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
You need to add the FK attribute on your navigation property. EF is creating Type_Id1 because Type_Id already exists (although it can't tell by convention it is the FK).
[ForeignKey("Type_Id")]
public virtual TaskType Type { get; set; }
https://msdn.microsoft.com/en-us/data/jj591583.aspx#Relationships
My issue is the following. I have a Model for an Address table as follows.
public partial class ADDRESS
{
public ADDRESS()
{
this.ADDRESS_ID = Guid.NewGuid();
}
public Guid ADDRESS_ID { get; set; }
public string ADDRESS_LINE { get; set; }
public string CITY { get; set; }
public Guid? STATE_ID { get; set; }
public string ZIP { get; set; }
}
This ADDRESS model is used throughout my application and has different validation requirements depending on where it is placed within a form.
I am wondering if there is a way to customize the data annotations. For example, the ADDRESS_LINE and CITY properties are required for OCCUPATION_ADDRESS but not required for WORK_LOCATION_ADDRESS.
public class OCCUPATION_DETAILS
{
public string COMPANY_NAME { get; set; }
public string JOB_TITLE { get; set; }
etc...
public Guid OCCUPATION_ADDRESS_ID { get; set; }
public virtual ADDRESS OCCUPATION_ADDRESS { get; set; }
public WORK_LOCATION_ID { get; set; }
public virtual ADDRESS WORK_LOCATION_ADDRESS { get; set; }
}
Or it could be that basic validation is the same (zip has to be 5 digits), but I need to adjust the "DisplayName" that is used to match the label of the form it is within.
Trying to minimize the amount of copied models I have set up; otherwise maintenance will be a nightmare.
you can achieve this by using the idea of inheritance
how?
public abstract class ADDRESS
{
public ADDRESS()
{
this.ADDRESS_ID = Guid.NewGuid();
}
public Guid ADDRESS_ID { get; set; }
public string ADDRESS_LINE { get; set; }
public string CITY { get; set; }
public Guid? STATE_ID { get; set; }
public string ZIP { get; set; }
}
public parital class OCCUPATION_ADDRESS: ADDRESS,IValidatableObject
{
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if(string.IsNullOrWhiteSpace(ADDRESS_LINE))
yield return new ValidationResult("Address line is required!",new string[]{"ADDRESS_LINE"});
}
}
public parital class WORK_LOCATION_ADDRESS: ADDRESS,IValidatableObject
{
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
}
}
// and your Occupation details class will be like: instead of ADDRESS you will use the corresponding derived classes
public class OCCUPATION_DETAILS
{
public string COMPANY_NAME { get; set; }
public string JOB_TITLE { get; set; }
etc...
public Guid OCCUPATION_ADDRESS_ID { get; set; }
public virtual OCCUPATION_ADDRESS OCCUPATION_ADDRESS { get; set; }
public WORK_LOCATION_ID { get; set; }
public virtual WORK_LOCATION_ADDRESS WORK_LOCATION_ADDRESS { get; set; }
}
and the inheritance should be Table per Hierarchy (TPH)
for more information about TPH check this Table per hierarchy
hope that this will help you
regards