I have two classes like so:
[Table("GameLevels", Schema = "ref")]
public class GameLevel
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public double PointsMin { get; set; }
public double PointsMax { get; set; }
}
[Table("GameProfiles", Schema = "usr")]
public class UserGameProfile
{
[Key]
[ForeignKey("ApplicationUser")]
public string Id { get; set; }
public int GamesPlayed { get; set; }
public double Points { get; set; }
public int WinCount { get; set; }
public int LossCount { get; set; }
public int DrawCount { get; set; }
public int ForfeitCount { get; set; }
public int GameLevelId { get; set; }
public virtual GameLevel Level { get; set; }
public virtual ApplicationUser ApplicationUser { get; set; }
}
Entity framework builds this so that UserGameProfile has a foreign key pointing to GameLevel. I guess this is because of the GameLevelId property.
Is there any way I can get this to generate the tables and navigation property without the foreign key?
I tried:
modelBuilder.Entity<UserGameProfile>().HasOptional<GameLevel>(x => x.Level).WithMany();
But then database fails to build. With this error:
One or more validation errors were detected during model generation:
Project.Domain.Data.UserGameProfile_Level: : Multiplicity
conflicts with the referential constraint in Role
'UserGameProfile_Level_Target' in relationship
'UserGameProfile_Level'. Because all of the properties in the
Dependent Role are non-nullable, multiplicity of the Principal Role
must be '1'.
Basically what I want is a zero-or-one to zero-or-many relationship.
How do I keep levels independent but have the ability to add a level to a profile?
You can't drop the foreign key completely, otherwise, how do you expect the two entities (i.e, tables) to be linked? What you can do instead is have a nullable FK, which will effectively make the relationship zero-or-one to many.
In your GameLevel class, add a navigation property as a collection of UserGameProfile:
public class GameLevel
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public double PointsMin { get; set; }
public double PointsMax { get; set; }
public virtual ICollection<UserGameProfile> UserGameProfiles { get; set; }
}
Then in the UserGameProfile class, make the property GameLevelId nullable:
public class UserGameProfile
{
// ...
// ...
public int? GameLevelId { get; set; }
[ForeignKey("GameLevelId")]
public virtual GameLevel GameLevel { get; set; }
}
This should work without even having to use Fluent API.
Related
I am using Entity Framework with fluent mapping.
In my application I want to fetch data from a view which is not having a key.
I have written a entity mapping for fluent api and a method to fetch data from view
When I tried to test the method, I get an error:
Entity Type has no key defined, Define a key for this entity type
Can I fetch data from view with out a key using Entity Framework with fluent.
below is the entity class
public class WeatherData : BaseModel
{
public DateTime ReportDateTime { get; set; }
public string VendorName { get; set; }
public string WeatherTypeCd { get; set; }
public string WeatherStationCd { get; set; }
public DateTime WeatherDate { get; set; }
public int Interval { get; set; }
public string IntervalTypeCd { get; set; }
public string WeatherValueTypeCd { get; set; }
public decimal ValueMax { get; set; }
public decimal ValueMin { get; set; }
public decimal ValueAvg { get; set; }
public string Unit { get; set; }
public int DegreeDayBase { get; set; }
public string UpdateUser { get; set; }
public DateTime UpdateDt { get; set; }
public int VendorId { get; set; }
public int WeatherStationId { get; set; }
public int WeatherTypeId { get; set; }
public int IntervalTypeId { get; set; }
public int WeatherValueTypeId { get; set; }
}
This is the mapping class
public class WeatherDataMap : EntityTypeConfiguration<WeatherData>
{
public WeatherDataMap() : base()
{
this.ToTable("dbo.vw_WeatherData");
}
}
I cannot change the view, I only have read permissions.
There is no problem if your table or view does not have primary key, but to avoid that mentioned exception your model must have PK so as the EF-Code First documentation says you can define Key a PK on more then one column or on one column so your model would be like :
public partial class WeatherData : BaseModel
{
[Key]
[Column(Order = 0)]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int VendorId { get; set; }
[Key]
[Column(Order = 1)]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int WeatherStationId { get; set; }
[Key]
[Column(Order = 2)]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int IntervalTypeId { get; set; }
[StringLength(50)]
public string VendorName { get; set; }
[StringLength(50)]
public string WeatherTypeCd { get; set; }
}
To use Find method of a DbSet you must take this order for the key parameters.
But please note if you generate EF-Code first model by POCO or Wizard the EF define all the int columns as the primary key as you can see in the above model, but you can define one prop as key but you should be sure there is no duplicated field which you defined as the key otherwise you should combine multiple columns as the primary key...
The other way is use Fluent Api to define key as the below code in OnModelCreating of your context:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<WeatherData>().Property(a => a.VendorId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
modelBuilder.Entity<WeatherData>().Property(a => a.WeatherStationId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
modelBuilder.Entity<WeatherData>().HasKey(w => new
{
w.VendorId,
w.WeatherStationId
});
}
Iam trying to create one to one relationship with my models. But I'm getting following error: " Multiplicity is not valid in Role 'DetayAcıklama_UrunBilgi_Target' in relationship 'DetayAcıklama_UrunBilgi'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'."
My models are like below:
public class Urun
{
[Key]
public int UrunID { get; set; }
[Required]
public string UrunKodu { get; set; }
[Required]
public decimal Fiyat { get; set; }
[ForeignKey("DetayBilgi")]
public int DetayAcıklamaID { get; set; }
public DetayAcıklama DetayBilgi { get; set; }
}
public class DetayAcıklama
{
[Key]
public int DetayAcıklamaID { get; set; }
[Display(Name = "Açıklama")]
public string AcıklamaTxt { get; set; }
public decimal Fiyat { get; set; }
[Required, ForeignKey("UrunBilgi")]
public int UrunID { get; set; }
public Urun UrunBilgi { get; set; }
}
What am I missing? Thanks in advance
Your current implementation doesn't say which is dependent table on which table.. for that specify a primary key column as the foreign key:
[Key, ForeignKey("UrunBilgi")]
public int DetayAcıklamaID { get; set; }
Very simple question but it looks like I'm trying to implement a simple one-to-many relationship between two models.
So far, what I have is this :
A product class :
public class Products
{
public long Id { get; set; }
public long Code { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateModified { get; set; }
public Boolean Reviewed { get; set; }
[ForeignKey("BundleId")]
public int BundleId { get; set; }
public virtual Bundles Bundle { get; set; }
}
And the Defects class looks like this:
public class Defects
{
public long Id { get; set; }
public String Description { get; set; }
public String Picture { get; set; }
public DateTime DateCreated { get; set; }
[ForeignKey("ProductId")]
public int ProductId { get; set; }
public Products Product { get; set; }
[ForeignKey("UserId")]
public int UserId { get; set; }
public virtual Users User { get; set; }
}
I thought that I did not need to add an ICollection of Defects to the Products class because it's a "simple" one-to-many relationship and this code would be enought to be able to get the ID of a Product in the Defects class (I don't need more).
But, of course I get an exception :
The property 'ProductId' cannot be configured as a navigation property. The property must be a valid entity type and the property should have a non-abstract getter and setter
How may I solve that issue ?
I might be doing someting wrong with my two foreign keys but since I declared the name of the foreign keys, I assumed it would have been enought.
Thanks for your attention.
This is what your relationship can be distilled to.
Please note that ForeignKey annotation is applied to navigation property with the name of the key property.
If you build one-to-many relationship - then ICollection is absolutely necessary. Otherwise where's the "many"
public class Products
{
public int Id { get; set; }
public virtual List<Defects> Bundle { get; set; }
}
public class Defects
{
public long Id { get; set; }
public int ProductId { get; set; }
[ForeignKey("ProductId")]
public Products Product { get; set; }
}
FK can also be applied to the key property. But in that case you have to put the name of the instance of related class there
public class Defects
{
public long Id { get; set; }
[ForeignKey("Product")]
public int ProductId { get; set; }
public Products Product { get; set; }
}
I am working on ASP.NET application with Entity Framework 6. I have already database and I am using Code First existing Database approach.
I am two table and second table has Foriegn key along with its own primary key. I have used Column order but still getting following error. I have search online, tried different combination but still getting error.
'System.Data.Entity.ModelConfiguration.ModelValidationException' occurred in EntityFramework.dll but was not handled in user code Sys_Nav_FunctionHierarchyEntity_Sys_Nav_FunctionEntity_Source: : Multiplicity is not valid in Role 'Sys_Nav_FunctionHierarchyEntity_Sys_Nav_FunctionEntity_Source' in relationship 'Sys_Nav_FunctionHierarchyEntity_Sys_Nav_FunctionEntity'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.
Class A
[Table("Sys_Nav_Function")]
public class Sys_Nav_FunctionEntity
{
public Sys_Nav_FunctionEntity()
{ }
[Key]
public int Function_ID { get; set; }
[StringLength(250)]
[Required(ErrorMessage = "Required Title")]
[Display(Name = "Function Title")]
public string FunctionName { get; set; }
[Required(ErrorMessage = "Required Hierarchy Level")]
[Display(Name = "Hierarchy Level")]
public int Hierarchy_Level { get; set; }
public Sys_Nav_FunctionHierarchyEntity Sys_Nav_FunctionHierarchyEntity { get; set; }
public ICollection<Sys_Nav_FunctionInActionEntity> Sys_Nav_FunctionInActionEntity { get; set; }
public ICollection<Sys_Nav_FunctionInControllerEntity> Sys_Nav_FunctionInControllerEntity { get; set; }
}
Class B
[Table("Sys_Nav_FunctionHierarchy")]
public class Sys_Nav_FunctionHierarchyEntity
{
public Sys_Nav_FunctionHierarchyEntity()
{
}
[Key, Column(Order =0)]
public int Hierarchy_ID { get; set; }
[ForeignKey("Sys_Nav_FunctionEntity"), Column(Order =1)]
public int Function_ID { get; set; }
public int Parent_Function_ID { get; set; }
public Sys_Nav_FunctionEntity Sys_Nav_FunctionEntity { get; set; }
}
Try this
[Table("Sys_Nav_FunctionHierarchy")]
public class Sys_Nav_FunctionHierarchyEntity
{
public Sys_Nav_FunctionHierarchyEntity()
{
}
[Key, Column(Order =0)]
public int Hierarchy_ID { get; set; }
[ForeignKey("Function_ID"), Column(Order =1)]
public int Function_ID { get; set; }
public int Parent_Function_ID { get; set; }
public Sys_Nav_FunctionEntity Sys_Nav_FunctionEntity { get; set; }
}
The foriegn key you have in class B is linked to the table and not to the property.
I believe the above code should give you the correct result
I think that the ForeignKey attribute should be set on the navigation property:
[Table("Sys_Nav_FunctionHierarchy")]
public class Sys_Nav_FunctionHierarchyEntity
{
//...
public int Function_ID { get; set; }
[ForeignKey("Function_ID")]
public Sys_Nav_FunctionEntity Sys_Nav_FunctionEntity { get; set; }
}
If Parent_Function_ID is also a foreign key to the same table, you can do it the same way.
Also, in the first class:
public Sys_Nav_FunctionHierarchyEntity Sys_Nav_FunctionHierarchyEntity { get; set; }
should be a collection (if I understood the probem correctly)
I have remove composite key, I have tried different combination but no luck, however its working by using same key as foreign key and also changed in database.
[Table("Sys_Nav_FunctionHierarchy")]
public class Sys_Nav_FunctionHierarchyEntity
{
public Sys_Nav_FunctionHierarchyEntity()
{
}
[Key, ForeignKey("Sys_Nav_FunctionEntity")]
[Required]
public int Function_ID { get; set; }
public int Parent_Function_ID { get; set; }
public Sys_Nav_FunctionEntity Sys_Nav_FunctionEntity { get; set; }
}
this is the error I'm getting:
"Introducing FOREIGN KEY constraint FK_dbo.RolePermissions_dbo.Permissions_Permission_ID on table RolePermissions may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint or index. See previous errors."
and here are my classes:
public class Permission
{
[Key]
public int ID { get; set; }
[Required]
public int PermissionObjectId { get; set; }
public PermissionObject PermissionObject { get; set; }
[Required]
public int CategoryId { get; set; }
public Category Category { get; set; }
[Required]
public int ReadWriteId { get; set; }
public ReadWrite ReadWrite { get; set; }
public virtual ICollection<Role> Roles { get; set; }
}
public class Role
{
[Key]
public int ID { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int CategoryId { get; set; }
public Category Category { get; set; }
public virtual ICollection<Permission> Permissions { get; set; }
}
public class Category
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
public int OrderID { get; set; }
public override string ToString()
{
return ID.ToString();
}
}
what do I do wrong?
use fluent api for set CascadeOndelete = fasle .
See This Link May Be Help you : Link
It looks like EF is trying to create a relationship of some sort between Roles and Permissions (many-to-many?), but you also have one-to-many relationships for category-role and category-permission which also have cascade delete enabled.
For foreign key relationships when using non-nullable keys or [Required], (e.g. CategoryId in both Role and Permission), cascade delete is enabled by default.