Entity Framework One to One Fluent Api Can not Delete Data - c#

That is the Gift class in model. That should be the parent class.
public class Gift
{
public int GiftId { get; set; }
public string Title { get; set; }
public string Brand { get; set; }
public double Price { get; set; }
public bool Chosen { get; set; }
public virtual Shop Shop { get; set; }
public virtual Person Person { get; set; }
}
That is the Shop class and these two have one to one relationship. A gift shoud have a shop, and a shop should have a gift.
public class Shop
{
public int ShopId { get; set; }
public string Name { get; set; }
public string Street { get; set; }
public string Number { get; set; }
public string Postcode { get; set; }
public string District { get; set; }
public virtual Gift Gift { get; set; }
}
That is the third class in my model. This class has one to zero relationship with the gift class. If a gift is not chosen, it does not have any person. Same for the person too.
public class Person
{
public int Id { get; set; }
public string FirstName{ get; set; }
public string Surname{ get; set; }
public string EmailAdress { get; set; }
public virtual Gift Gift { get; set; }
}
Here is the fluent api that i have lots of times changed.
modelBuilder.Entity<Gift>()
.HasOptional(x => x.Person);
modelBuilder.Entity<Person>()
.HasRequired(x => x.Gift);
modelBuilder.Entity<Gift>()
.HasRequired(x => x.Shop).WithOptional(x => x.Gift).Map(x => x.MapKey("ShopId"));
modelBuilder.Entity<Shop>()
.HasRequired(x => x.Gift).WithOptional(x => x.Shop).Map(x => x.MapKey("GiftId"));
I can save data but when i want to delete a gift, i can not succeed and have problems. How can i fix that? Thanx already!

I have fixed it. Here is the link
modelBuilder.Entity<Shop>()
.HasRequired(x => x.Gift)
.WithRequiredDependent();
modelBuilder.Entity<Gift>()
.HasRequired(x => x.Shop)
.WithRequiredPrincipal();
base.OnModelCreating(modelBuilder);

Related

EF ... Unwanted duplicate values of two fields

I have two entity for save Product and Product's Related Products ... there is One to Many Relationship ... Everything is right before storing the information But in the database two duplicate fields are stored
RelatedProducID
ProductID
public class RelatedCatalogs : EntityBase
{
public Guid ProductID { get; set; }
public Guid RelatedProducID { get; set; }
public Product RelatedProductCatalog { get; set; }
public int Priority { get; set; }
}
Product Class:
public class Product{
public Guid ProductID { get; set; }
public string Name { get; set; }
[ForeignKey("RelatedProductID")]
public virtual List<RelatedCatalogs> RelatedCatalogs { get; set; }
.
.
.
}
What needs to be done now to fix this problem?
Your problem seems similar to this, so try:
public class Product
{
public Guid ProductID { get; set; }
public string Name { get; set; }
...
[InverseProperty("Product")]
public virtual List<RelatedCatalogs> RelatedCatalogs { get; set; }
}
public class RelatedCatalogs : EntityBase
{
public Guid ID { get; set; }
[ForeignKey("Product")]
public Guid ProductID { get; set; }
public Product Product { get; set; }
[ForeignKey("RelatedProductCatalog")]
public Guid RelatedProductID { get; set; }
public Product RelatedProductCatalog { get; set; }
public int Priority { get; set; }
}
Then you can add the mentioned fluent code to avoid cycles:
modelBuilder.Entity<RelatedCatalogs>()
.HasRequired(r => r.RelatedProductCatalog)
.WithMany()
.HasForeignKey(r => r.RelatedProductID)
.WillCascadeOnDelete(false);
modelBuilder.Entity<RelatedCatalogs>()
.HasRequired(r => r.Product)
.WithMany(p => p.RelatedCatalogs)
.HasForeignKey(r => r.ProductID);

ManyToMany Database With Three Models

I have more of a theoretical question. I have three Models. Employee, Commission and Position. Currently I created a ManyToMany relationship database EmployeeCommission (an Employee has many Commissions and Commissions have many Employees) but I also need to add Position to the relationship which would make that Commissions have many Employees that can have many Positions and so on. (Same employee can have different positions in different commissions).
How do I go about this? I know that ManyToMany relationship can only be between to models, so how do I create a ManyToMany database between three models?
Here's my Models, but I don't think you'll need them, but just for general information.
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
[Display(Name = "Phone Number")]
public int PhoneNumber { get; set; }
}
public class Commission
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
public class Position
{
public int Id { get; set;}
public string Name { get; set; }
}
Note: I am using CodeFirst approach.
You can View thisexample to do that:
public class User
{
public int Id { get; set; }
public ICollection<UserAccount> UserAccounts { get; set; }
}
public class Account
{
public int Id { get; set; }
public ICollection<UserAccount> UserAccounts { get; set; }
}
public class UserAccount
{
public int UserId { get; set; }
public int AccountId { get; set; }
public int RoleId { get; set; }
public User User { get; set; }
public Account Account { get; set; }
public Role Role { get; set; }
}
public class Role
{
public int Id { get; set; }
public string RoleName { get; set; }
public ICollection<UserAccount> UserAccounts { get; set; }
}
Configuration:
modelBuilder.Entity<UserAccount>()
.HasKey(e => new { e.UserId, e.AccountId });
modelBuilder.Entity<UserAccount>()
.HasRequired(e => e.User)
.WithMany(e => e.UserAccounts)
.HasForeignKey(e => e.UserId);
modelBuilder.Entity<UserAccount>()
.HasRequired(e => e.Account)
.WithMany(e => e.UserAccounts)
.HasForeignKey(e => e.AccountId);
modelBuilder.Entity<UserAccount>()
.HasRequired(e => e.Role)
.WithMany(e => e.UserAccounts)
.HasForeignKey(e => e.RoleId);
You can create a new UserAccount in a several ways.

Automapper - Unable to map nested objects/collecions

I've tried numerous examples on here and from the automapper wiki and I am still unable to get this issue resolved. I am trying to map a nested object and a nested collection and no matter what I do it always throws an error. The only way I can get the controller to return data is by turning on option.ignore for the two properties.
These are the business layer objects I am trying to map
public class LocationBL
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zipcode { get; set; }
public string Country { get; set; }
public DbGeography Coordinates { get; set; }
public int LocationType_Id { get; set; }
public virtual LocationTypeBL LocationType { get; set; }
public virtual ICollection<SportBL> Sports { get; set; }
}
public class LocationTypeBL
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<LocationBL> Locations { get; set; }
}
public class SportBL
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<LocationBL> Locations { get; set; }
public virtual ICollection<UserBL> Users { get; set; }
}
These are the data layer objects
public class Location : EntityData
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[ForeignKey("Company")]
public int? CompanyId { get; set; }
[Required]
public string Name { get; set; }
public string Address { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zipcode { get; set; }
public string Country { get; set; }
[Required]
public DbGeography Coordinates { get; set; }
[ForeignKey("LocationType")]
public int LocationType_Id { get; set; }
public virtual LocationType LocationType { get; set; }
public virtual ICollection<Sport> Sports { get; set; }
public virtual Company Company { get; set; }
}
public class LocationType : EntityData
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Location> Locations { get; set; }
}
public class Sport : EntityData
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public virtual ICollection<Location> Locations { get; set; }
public virtual ICollection<User> Users { get; set; }
}
This is my mapping profile
public class LocationProfile : Profile
{
public LocationProfile()
{
CreateMap<LocationType, LocationTypeBL>();
CreateMap<LocationTypeBL, LocationType>();
CreateMap<Location, LocationBL>()
.ForMember(Dest => Dest.Sports,
opt => opt.MapFrom(src => src.Sports))
.ForMember(Dest => Dest.LocationType,
opt => opt.MapFrom(src => src.LocationType));
CreateMap<LocationBL, Location>()
.ForMember(Dest => Dest.Sports,
opt => opt.MapFrom(src => src.Sports))
.ForMember(Dest => Dest.LocationType,
opt => opt.MapFrom(src => src.LocationType));
}
}
UPDATE *******
This is my LocationType profile
public class LocationTypeProfile : Profile
{
public LocationTypeProfile()
{
CreateMap<LocationType, LocationTypeBL>();
CreateMap<LocationTypeBL, LocationType>();
}
}
This is my Sport profile
public class SportProfile : Profile
{
public SportProfile()
{
CreateMap<Sport, SportBL>();
CreateMap<SportBL, Sport>();
}
}
Not sure if it matters but this is an Azure Mobile App backend using Autofac, WebAPI, and OWIN. This is my first time using AutoMapper and Autofac so please forgive me as I am still learning. The profiles are all registered and if I set the nested objects to ignore, the controller returns the proper data.
Thank you in advance!!!
You are almost there. You need to instruct AutoMapper on how to map the nested objects as well. So you need to create a map for the Sport to SportBL, and vice-versa, also.
// use ForMember if needed, but you know how to do that so I won't
// show it.
CreateMap<Sport, SportBL>();
Then AutoMapper will use that mapping when it mapping nested complex types.
Another note, if your classes have the same properties, you can just call the ReverseMap() method and it will do bidirectional mapping for you.
So instead of this:
CreateMap<LocationType, LocationTypeBL>();
CreateMap<LocationTypeBL, LocationType>();
You can just do this to accomplish the same thing:
Mapper.CreateMap<LocationType, LocationTypeBL>().ReverseMap();

Entity Framework Unable to determine principal end of relationship. Multiple added entities may have same primary key

I'm having some issues with EF.
Migrations go fine, but when I try to run update-database I get the error :
Unable to determine the principal end of the 'LeagueInsight.Models.Image_Passive' relationship. Multiple added entities may have the same primary key.
Here are my models and config:
Passive.cs
public class Passive
{
public long Id { get; set; }
public string Description { get; set; }
public string Name { get; set; }
public string SanitizedDescription { get; set; }
// Navigation
public virtual Image Image { get; set; }
public virtual Champion Champion { get; set; }
}
Image.cs
public class Image
{
public long Id { get; set; }
public string Full { get; set; }
public string Group { get; set; }
public int H { get; set; }
public string Sprite { get; set; }
public int W { get; set; }
public int X { get; set; }
public int Y { get; set; }
// Navigation
public virtual Champion Champion { get; set; }
public virtual ChampionSpell ChampionSpell { get; set; }
public virtual Passive Passive { get; set; }
}
DBContext Configuration Partial:
modelBuilder.Entity<Passive>()
.HasRequired(p => p.Champion)
.WithRequiredPrincipal(c => c.Passive);
modelBuilder.Entity<Info>()
.HasRequired(i => i.Champion)
.WithRequiredPrincipal(c => c.Info);
modelBuilder.Entity<Image>()
.HasOptional(i => i.Champion)
.WithRequired(c => c.Image);
modelBuilder.Entity<Image>()
.HasOptional(i => i.Passive)
.WithRequired(p => p.Image);
base.OnModelCreating(modelBuilder);
It is just supposed to be a 1-1 relationship between the two, an I can't figure out why there would be multiple entities with the same Id here.
Edit: I was asked for the champion class:
public class Champion
{
public int Id { get; set; }
public string Blurb { get; set; }
public string Key { get; set; }
public string Lore { get; set; }
public string Name { get; set; }
public string Partype { get; set; }
public string Title { get; set; }
// Navigation
[InverseProperty("Ally")]
public virtual ICollection<Tip> Allytips { get; set; }
[InverseProperty("Enemy")]
public virtual ICollection<Tip> Enemytips { get; set; }
public virtual Image Image { get; set; }
public virtual Info Info { get; set; }
public virtual Passive Passive { get; set; }
public virtual ICollection<Recommended> Recommended { get; set; }
public virtual ICollection<Skin> Skins { get; set; }
public virtual Stats Stats { get; set; }
public virtual ICollection<ChampionSpell> Spells { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
}

Entity Framework Code First Mapping

I have two classes, the Group class has a many to many relationship with the User class (representing the groups a user belongs to) and then the group also has a relationship of one to many with the user class (representing the owner of a group).
How can I map this?
public class User
{
public int Id { get; set; }
public string Avatar { get; set; }
public string Name { get; set; }
public string Message { get; set; }
public virtual ICollection<Group> OwnedGroups { get; set; }
public virtual ICollection<Group> Groups { get; set; }
}
public class Group
{
public int Id { get; set; }
public DateTime CreateDate { get; set; }
public DateTime ModifyDate { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool System { get; set; }
public int ViewPolicy { get; set; }
public int JoinPolicy { get; set; }
public string Avatar { get; set; }
public int Order { get; set; }
public int GroupType { get; set; }
public virtual User Owner { get; set; }
public virtual ICollection<User> Members { get; set; }
}
tks in advance!
I would use fluent API:
public class Context : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Group> Groups { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>()
.HasMany(u => u.Groups)
.WithMany(g => g.Members);
modelBuilder.Entity<User>()
.HasMany(u => u.OwnedGroups)
.WithRequired(g => g.Owner)
.WillCascadeOnDelete(false);
}
}
It should also be possible with Data annotations:
public class User
{
...
[InverseProperty("Owner")]
public virtual ICollection<Group> OwnedGroups { get; set; }
[InverseProperty("Members")]
public virtual ICollection<Group> Groups { get; set; }
}
public class Group
{
...
[InverseProperty("OwnedGroups")]
public virtual User Owner { get; set; }
[InverseProperty("Groups")]
public virtual ICollection<User> Members { get; set; }
}
InverseProperty is not needed on both sides of relation but it does definition clearer.

Categories