Using Entity Framework Data Annotations to Achieve One to Many Relationship With Eager Loading - entity-framework

I've seen plenty of examples not using Data Annotations and can get a one-to-one relationship working, but having difficulty with a one-to-many.
We have parts that we will randomly take sample weights on to make sure our machine house is producing to spec. The one-to-one relationship for Material will load. Having trouble with the QualityMeasurements one-to-many.
Anyone have experience with this?
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
public class Part {
[Key]
public string PartID { get; set; }
public string PartNumber { get; set; }
[ForeignKey("MaterialID")]
public virtual Material Material { get; set; }
public int MaterialID { get; set; }
[ForeignKey("PartNumber")]
public virtual ICollection<QualityMeasurement> Qualities { get; set; }
}
public class Material {
[Key]
public int MaterialID { get; set; }
public string Title { get; set; }
public double Density { get; set; }
}
public class QualityMeasurement {
public int QualityID { get; set; }
[Key]
public string PartNumber { get; set; }
public double UnitWeight { get; set; }
}

You are having troubles because in the one-to-many relationship, the foreign key should be defined at the many side and should relate to the primary key of the one side.
Your model should be something like this:
public class Part {
[Key]
public string PartID { get; set; }
public string PartNumber { get; set; }
[ForeignKey("MaterialID")]
public virtual Material Material { get; set; }
public int MaterialID { get; set; }
public virtual ICollection<QualityMeasurement> Qualities { get; set; }
}
public class QualityMeasurement {
[Key]
public int QualityID { get; set; }
[ForeignKey("PartID")]
public virtual Part Part { get; set; }
public string PartID { get; set; }
public double UnitWeight { get; set; }
}

Related

entity framework migration up table relationships incorrect?

Simple model to demonstrate three types of relationships:
One-To-One - Deed and House: House has 1 deed and 1 deed is for that house
One-To-Many - House -> Room: My House has many rooms
Many-To-Many - Room <-> Color: The Many rooms can have many of the same colors
The classes (without the constructors):
public class Deed {
public int DeedId { get; set; }
public string Owner { get; set; }
public House Home { get; set; }
public class House
{
public int HouseId { get; set; }
public string Address { get; set; }
public List<Room> Rooms { get; set; }
public class Room
{
public int RoomId { get; set; }
public string Name { get; set; }
List<Color> Colors { get; set; }
public class Color
{
public int ColorId { get; set; }
public string ColorName { get; set; }
public List<Room> Rooms { get; set; }
My confusion is in the Migration UP constructors:
First the one to one: I get an error when Deed and House point to each other saying it cannot determine the "principle". So I made Deed the principle:
Next House has Many Rooms. I think I understand that the foreign key is ONLY in each room pointing back to the house like this:
Next is where I really get confused. I would expect the Many ROOMS share Many COLORS (many to many)... each would point to the other. BUT:
I appreciate your advice.
Thanks in advance,
Yogi ("Chuck")
Try this minor cleanup of your model. Also why wouldn't a House have multiple Deeds? And anyway EF6 makes it hard to model 1-1 relationships. You either have to make the DeedId the FK to House, or make Deed a Complex Type instead of an Entity.
public class Deed
{
public int DeedId { get; set; }
public string Owner { get; set; }
public int HouseId { get; set; }
public House House { get; set; }
}
public class House
{
public int HouseId { get; set; }
public string Address { get; set; }
public virtual ICollection<Room> Rooms { get; } = new HashSet<Room>();
}
public class Room
{
public int RoomId { get; set; }
public string Name { get; set; }
public int HouseId { get; set; }
public House House { get; set; }
public virtual ICollection<Color> Colors { get; } = new HashSet<Color>();
}
public class Color
{
public int ColorId { get; set; }
public string ColorName { get; set; }
public virtual ICollection<Room> Rooms { get; } = new HashSet<Room>();
}
public class MyDbContext : DbContext
{
public DbSet<Deed> Deeds { get; set; }
public DbSet<House> Houses { get; set; }
public DbSet<Room> Rooms { get; set; }
public DbSet<Color> Colors { get; set; }
}

Entity framework relation mapping is not working

print("Hello World !");
I'm a beginner into the .NET world, i'm trying to use entity framework but i have a problem, my relations entities are not loaded, i followed the microsoft documentation but.
Here are my models :
[Table("Path")]
public class Path
{
[Key]
public int PathId { get; set; }
[Required]
public string Title { get; set; }
public List<Image> Images { get; set; }
[Required]
public string Description { get; set; }
[Required]
public float LocationX { get; set; }
[Required]
public float LocationY { get; set; }
[Required]
public string QrCode { get; set; }
public List<Mark> Marks { get; set; }
}
[Table("Mark")]
public class Mark
{
[Key]
public int MarkId { get; set; }
public int Value { get; set; }
public int PathForeignKey { get; set; }
[ForeignKey("PathForeignKey")]
public Path Path { get; set; }
}
[Table("Image")]
public class Image
{
[Key]
public int ImageId { get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
public int PathForeignKey { get; set; }
[ForeignKey("PathForeignKey")]
public Path Path { get; set; }
[Required]
public string Source { get; set; }
}
For me, everything is ok, i even have the correct entries into my database :
database entries
But my relation dont load when i'm reading database into my controller.
[HttpGet]
public IEnumerable<Path> GetAll()
{
return _context.Paths.ToList();
}
results
I'm sorry, i guess it is probably a stupid beginner error but i dont see what i did wrong. I tried with various database system, with virtual or not ...
Mark your navigation properties as virtual. For example:
[Table("Mark")]
public class Mark
{
[Key]
public int MarkId { get; set; }
public int Value { get; set; }
public int PathForeignKey { get; set; }
[ForeignKey("PathForeignKey")]
public virtual Path Path { get; set; } //Added virtual keyword
}
and a second way to load navigation properties is to use Include while fetching data:
return _context.Marks.Include(x => x.Path).ToList();

Map many to many objects using Entity Framework

For example we have profile and organisation. Both have articles.
public class Article
{
public int Id { get; set; }
public string Title { get; set; }
}
public class Profile
{
public int Id { get; set; }
public string Email { get; set; }
public virtual ICollection<Article> Articles { get; set; }
}
public class Organisation
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Article> Articles { get; set; }
}
In this way Article should have two kinds of parent so it should have something like parent type to be able to access a parent when you select articles directly.
public class Article
{
public int Id { get; set; }
public string Title { get; set; }
public int ParentId { get; set; }
public ArticleParentType Parent { get; set; }
}
Is it possible to map it using Entity Framework?
Is it a good idea to do it?
What is the best practice for storing this kind of data?
public class Article
{
public int Id { get; set; }
public string Title { get; set; }
public int ParentId { get; set; }
public ArticleParentType Parent { get; set; }
}
Is it possible to map it using Entity Framework?
Is it a good idea to do it?
Possible yes but not a good idea. The underlying Database can't use a foreign key for Parentid. It would be slow.
What is the best practice for storing this kind of data?
A simple approach, with 2 Nullable parents and without CascadeOnDelete:
public class Article
{
public int Id { get; set; }
public string Title { get; set; }
public virtual Profile Profile { get; set; }
public virtual Organisation Organisation { get; set; }
}
Alternatively you could use inheritance for Article, ie class OrganisationArticle : Article {}

Error in many-to-many relationship using Fluent API in Entity Framework 6 one model is self referencing

Category model is self referencing
public class Category
{
[Key]
public int CategoryID { get; set; }
public string Name { get; set; }
public int? ParentID { get; set; }
public Category Cat { get; set; }
public ICollection<Category> Categories { get; set; }
public ICollection<BusinessDetail> BDetails { get; set; }
}
and BusinessDetail is like
public class BusinessDetail
{
[Key]
public int ID { get; set; }
[Required]
[Display(Name="Business Name")]
public string BusinessName { get; set; }
public string Address { get; set; }
[Display(Name="Contact")]
public string contactDetail { get; set; }
// public int CategoryID { get; set; }
// public Category Category { get; set; }
public int ? LocationID { get; set; }
public Location Location { get; set; }
[Display(Name="Website Address")]
public string Website_Address { get; set; }
[Display(Name="Is Verified")]
public bool Is_verified { get; set; }
[Required]
[Display(Name="Added By")]
public string Added_By { get; set; }
[Required]
[Display(Name="Added Date")]
[DataType(DataType.DateTime)]
public DateTime Added_Date { get; set; }
[Display(Name="Is Featured")]
public bool Is_Featured { get; set; }
public string Latitude { get; set; }
public string VerifiedBy { get; set; }
public string Longitude { get; set; }
public ICollection<Category> Categories { get; set; }
}
When creating a many-to-many relationship using Fluent API
modelBuilder.Entity<BusinessDetail>()
.HasMany(c => c.Categories).WithMany(i => i.BDetails)
.Map(t => t.MapLeftKey("ID")
.MapRightKey("CategoryID")
.ToTable("BusinessCategories"));
I get this error
There are no primary or candidate keys in the referenced table
'dbo.BusinessDetails' that match the referencing column list in the
foreign key 'FK_dbo.BusinessCategories_dbo.BusinessDetails_ID'.
I need help on this error.
I will try to work out your exact example, but the code below works without any configuration:
EDIT:
I added in the code from OnModelCreating and changed the property names to those in your exampe, but it all keeps working. You do realize though, that the ParentId property is not seen as the foreign key for a parent Category, but that EF will create a Cat_CategoryId foreign key for you?
I advise to start from scratch using my code and work step by step towards the existing code.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Data.Entity;
public class CategoryContext : DbContext
{
public DbSet<Category> Categories { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Fill in later.
}
}
public class Category
{
public Category()
{
Children = new List<Category>();
Details = new List<BussinesDetail>();
}
public int Id { get; set; }
public string Name { get; set; }
public int? ParentId { get; set; }
public virtual Category Parent { get; set; }
public virtual ICollection<Category> Children { get; set; }
public virtual ICollection<BussinesDetail> Details { get; set; }
}
public class BussinesDetail
{
public int Id { get; set; }
public string BussinesName { get; set; }
public virtual ICollection<Category> Categories { get; set; }
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
static class Module1
{
public static void Main()
{
using (context = new CategoryContext()) {
var newCat = context.Categories.Add(new Category { Name = "CatOne" });
context.SaveChanges();
newCat = context.Categories.Single;
Console.WriteLine(newCat.Name);
Console.ReadLine();
}
}
}

EF5 CodeFirst + Relationships between non-key columns

In have two classes;
public class Item
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public virtual BinCard BinCard { get; set; }
}
and
public class BinCard
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public int ItemId { get; set; }
[Required]
public DateTime Date { get; set; }
[Required]
public double Qty { get; set; }
public ObservableCollection<Item> Item { get; set; }
}
The BinCard.Id is the PK and auto increments.
I want the relationship between two tables using Item.Id and BinCard.ItemId using*FluentAPI*.
Please help me to create this relationship correctly.
EF does not support non-PK principal Ids because it doesn't support unique keys other than PKs yet. To make this work you will have to create relationship based on BinCard.Id and BinCardId to Item entity - btw. it looks like the correct way to build relationship in your model. Your current model looks really strange.
Thanks for all replies. This is the solution for my question.
public class BinCard
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public int ItemId { get; set; }
[Required]
public DateTime Date { get; set; }
[Required]
public double Qty { get; set; }
public virtual Drug Drug { get; set; }
}
public class Item
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public ObservableCollection<BinCard> BinCard { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Drug>()
.HasRequired(s => s.Stock)
.WithRequiredPrincipal(s => s.Drug);
}