CTP5 vs release 4.1 EF many to many relationship - entity-framework

This code doesn't work. What is wrong? OnModelCreating doesnt't effect any result? Because I can not see "ProductCategories" table in my Database.
public class GoldContext : DbContext
{
public virtual DbSet<Prouct> Products { get; set; }
public virtual DbSet<Category> Categories { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//HACK:4.1 modelBuilder.Conventions.Add(new DecimalPrecisionAttributeConvention());
modelBuilder.Entity<Product>()
.HasMany<Category>(m => m.Categories)
.WithMany().Map(m =>
m.MapLeftKey("ProductId")
.MapRightKey("CategoryId")
.ToTable("ProductCategories"));
base.OnModelCreating(modelBuilder);
}
}
//product and category classes look like this.
public class Product
{
[Key]
public int Id { get; set; }
public virtual string Name { get; set; }
public virtual ICollection<Category> Categories { get; set; }
}
public class Category
{
[Key]
public int Id { get; set; }
public virtual string Name { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
Thanks in advance.

This is what I've tried in a console application and works as expected :
namespace Q7122388
{
#region Imports
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Linq;
#endregion
public class Product
{
[Key]
public int Id { get; set; }
public virtual string Name { get; set; }
public virtual ICollection<Category> Categories { get; set; }
}
public class Category
{
[Key]
public int Id { get; set; }
public virtual string Name { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
public class DatabaseContext : DbContext
{
public virtual DbSet<Product> Products { get; set; }
public virtual DbSet<Category> Categories { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.HasMany<Category>(m => m.Categories)
.WithMany().Map(m =>
m.MapLeftKey("ProductId")
.MapRightKey("CategoryId")
.ToTable("ProductCategories"));
base.OnModelCreating(modelBuilder);
}
}
class Program
{
static void Main(string[] args)
{
Database.SetInitializer(new DropCreateDatabaseAlways<DatabaseContext>());
using (var context = new DatabaseContext())
context.Database.Initialize(true);
}
}
}

Related

Entity Framework database-first : how to add property to a model that will reference itself?

I am trying to create a Product table that will have a list of SubstitutionProducts that should reference other Product from the same table.
Model example :
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsMissing { get; set; }
public ICollection<Product> SubstitutionProducts { get; set; }
}
It is better to include the parent ID in your model:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsMissing { get; set; }
public int? ParentId { get; set; }
public Product Parent { get; set; }
public ICollection<Product> SubStitutionProducts { get; set; }
}
This is how to configure DB schema via overriding OnModelCreatingmethod of your DbContext:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>().HasOne(x => x.Parent)
.WithMany(x => x.SubStitutionProducts)
.HasForeignKey(x => x.ParentId).IsRequired(false);
}

EF6 Code First - Multiple one-to-many and same entity

I have an entity model that contains multiple definitions to another entity. I can get one definition to work, but not both.
public class Inspection : Entity<int>
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int InspectionId { get; set; }
[ForeignKey("Report")]
public int ReportId { get; set; }
public virtual Report Report { get; set; }
....
public virtual ICollection<ResidentialDescriptionItem> ResidentialDescriptionItems { get; set; }
public virtual ICollection<ResidentialDescriptionItem> ResidentialOtherDescriptionItems { get; set; }
}
public class ResidentialDescriptionItem : Entity<int>
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ResidentialDescriptionItemId { get; set; }
public int InspectionId { get; set; }
[ForeignKey("InspectionId")]
public virtual Inspection Inspection { get; set; }
//public int Inspection1Id { get; set; }
//[ForeignKey("Inspection1Id")]
//public virtual Inspection Inspection1 { get; set; }
}
I've made numerous attempts with that second index and received just as many different errors. The above configuration results in
Unable to determine the principal end of the
'MySolution.EntityFramework.ResidentialDescriptionItem_Inspection'
relationship. Multiple added entities may have the same primary key.
I would like to maintain a full configuration with navigation on both sides. How do I do this using Code First and Annotations?
I don't think it is possible to implement such complex relationship with annotations, but here is a demo, how you would need to override your DbContext.OnModelCreating
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
namespace ConsoleApp3
{
public class Parent
{
[Key]
public int Id { get; set; }
public virtual ICollection<Child> Children { get; set; }
public virtual ICollection<Child> OtherChildren { get; set; }
}
public class Child
{
[Key]
public int Id { get; set; }
[ForeignKey("Parent")]
public int? ParentId { get; set; }
[ForeignKey("ParentId")]
public virtual Parent Parent { get; set; }
[ForeignKey("OtherParent")]
public int? OtherParentId { get; set; }
[ForeignKey("OtherParentId")]
public virtual Parent OtherParent { get; set; }
}
public class MyDbContext : DbContext
{
public MyDbContext(string nameOrConnectionString) : base(nameOrConnectionString)
{
}
public DbSet<Parent> Parents { get; set; }
public DbSet<Child> Children { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Parent>()
.HasMany(x => x.Children)
.WithOptional(x => x.Parent);
modelBuilder.Entity<Parent>()
.HasMany(x => x.OtherChildren)
.WithOptional(x => x.OtherParent);
}
}
class Program
{
static void Main(string[] args)
{
Database.SetInitializer(new DropCreateDatabaseAlways<MyDbContext>());
var ctx = new MyDbContext("Data Source=DESKTOP-5PVJ0I5;Database=test1;Integrated Security=true");
var parent = ctx.Parents.Add(new Parent());
ctx.Children.Add(new Child()
{
OtherParent = parent
});
ctx.Children.Add(new Child()
{
Parent = parent
});
ctx.SaveChanges();
parent = ctx.Parents
.Include(x => x.Children)
.Include(x => x.OtherChildren)
.FirstOrDefault();
}
}
}

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();
}
}
}

How to map many-to-many with Code First to same class?

I use Code First with Entity Framework 5.
I have User class, where one user can be friends with many people.
public class User
{
[Key]
public Guid UserID { get; set; }
public virtual ICollection<User> Friends { get; set; }
}
This however maps 0..1-to-many. How should I map many-to-many relationship with the same class in Code First?
Add configuration class:
public class UserConfiguration : EntityTypeConfiguration<User>
{
public UserConfiguration()
{
HasMany(u => u.Friends).WithMany();
}
}
then, this needs to be added to context class
public class MyContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new UserConfiguration());
base.OnModelCreating(modelBuilder);
}
}
public class Organization : Entity
{
public string Name { get; set; }
public string Description { get; set; }
public virtual Organization Parent { get; set; }
public virtual ICollection<Organization> Children { get; set; }
public virtual ICollection<User> Users { get; set; }
}
public class OrganizationConfiguration : EntityMapperBase<Organization>
{
public OrganizationConfiguration()
{
HasKey(f => f.Id);
Property(f => f.Name).HasMaxLength(20).IsRequired();
HasMany(f => f.Children).WithOptional(f => f.Parent).Map(m => m.MapKey("ParentId")).WillCascadeOnDelete(false);
HasMany(f => f.Users).WithRequired(f => f.Organization).Map(m => m.MapKey("OrganizationId"));
}
}
may it help you
You should have tow navigation properties
public class User
{
[Key]
public Guid UserID { get; set; }
public virtual ICollection<User> FriendsOfMine { get; set; }
public virtual ICollection<User> FriendsWithMe { get; set; }
}

Entity Framework Code First Membership Provider Relationship Issue

I'm trying to code first on asp.net membership provider. When code first creates the table, it generates all tables and appropriate relationship to the bridge table but it also create an additional relationship from the AspNet_User(one) to Aspnet_Role(many). Do you know why it doing this? There shouldn't be any relationship between user and role table.
public class Aspnet_Role
{
public Aspnet_Role()
{
Aspnet_Users = new HashSet<Aspnet_Users>();
}
[Key]
public Guid RoleId { get; set; }
public string RoleName { get; set; }
public string LoweredRoleName { get; set; }
public string Description { get; set; }
public virtual ICollection<Aspnet_Users> Aspnet_Users { get; set; }
}
public class Aspnet_Users
{
public Aspnet_Users()
{
Aspnet_Roles = new HashSet<Aspnet_Role>();
}
[Key]
public Guid UserId { get; set; }
public string UserName { get; set; }
public string LoweredUserName { get; set; }
public string MobileAlias { get; set; }
public bool IsAnonymous { get; set; }
public DateTime LastActivityDate { get; set; }
public virtual Aspnet_Membership Aspnet_Membership { get; set; }
public virtual ICollection<Aspnet_Role> Aspnet_Roles { get; set; }
}
public class StagingContext : DbContext
{
public DbSet<Aspnet_Role> Aspnet_Roles { get; set; }
public DbSet<Aspnet_Users> Aspnet_Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Aspnet_Users>()
.HasMany(r => r.Aspnet_Roles)
.WithMany()
.Map(m => m.ToTable("aspnet_UsersInRoles")
.MapRightKey("RoleId")
.MapLeftKey("UserId"));
}
}
I added the navigation property on the WithMany extension.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Aspnet_Users>()
.HasMany(r => r.Aspnet_Roles)
.WithMany(u => u.Aspnet_Users)
.Map(m => m.ToTable("aspnet_UsersInRoles")
.MapRightKey("RoleId")
.MapLeftKey("UserId"));
}