Entity Framework foreign key error in two connect class - c#

I use Entity Framework 6.1 in ASP.NET MVC.
My model is :
public class Article
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public double Price { get; set; }
[InverseProperty("Article")]
public virtual ICollection<FormulaItem> FormulaItem { get; set; }
}
public class FormulaItem
{
[Key]
[Column(Order = 0)]
public int Id { get; set; }
[ForeignKey("IdMaster")]
public virtual Formula Formula { get; set; }
public int IdMaster { get; set; }
[ForeignKey("IdArticle")]
public virtual Article Article { get; set; }
public int IdArticle { get; set; }
public string Comment { get; set; }
public int Count { get; set; }
}
public class Formula
{
[Key]
[Column(Order = 0)]
public int Id { get; set; }
public FormulaMode Mode { get; set; }
// Wen add this line I get error
//[ForeignKey("IdArticle")]
//public virtual Article Article { get; set; }
//public int? IdArticle { get; set; }
public string Comment { get; set; }
public virtual IList<FormulaItem> Items { get; set; }
public Formula()
{
Items = new List<FormulaItem>();
}
}
This sample works fine, but when add the new poco:
// When I add this line in class formula I get error
[ForeignKey("IdArticle")]
public virtual Article Article { get; set; }
public int? IdArticle { get; set; }
to class Formula I get error:
Formula_Items_Source_Formula_Items_Target: : The number of properties in the Dependent and Principal Roles in a relationship constraint must be identical

Consider using FluentAPI as it is more user-friendly:
modelBuilder.Entity<FormulaItem>()
.HasOptional(b => b.Article )
.WithMany(a => a.FormulaItem);
And in your case you must be missing another InverseProperty attribute:
[InverseProperty("FormulaItem")]
public virtual Article Article { get; set; }

I add:
modelBuilder.Configurations.Add(new FormulaConfig());
public class FormulaConfig : EntityTypeConfiguration<Formula>
{
public FormulaConfig()
{ // one-to-many
this.HasRequired(x => x.Article)
.WithOptional(x=>x.Formula)
.WillCascadeOnDelete();
}
}
but get error :
Article_Formula_Target: : Multiplicity is not valid in Role 'Article_Formula_Target' in relationship 'Article_Formula'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.

Related

Entity Framework Core One-to-One, Not Unique

Given two tables, TrackingTag and TrackingTagStatusUpdate:
public class TrackingTag
{
public int ID { get; set; }
}
public class TrackingTagStatusUpdate
{
public int ID { get; set; }
public int TrackingTagID { get; set; }
public TrackingTag TrackingTag { get; set; }
public int Epoch { get; set; } //32-bit
[MaxLength(32)]
public string APConnectedSSID { get; set; }
}
As there will be many TrackingTagStatusUpdates, I want to add a field "LatestStatusUpdate" to TrackingTag, for performance reasons.
public class TrackingTag
{
public int ID { get; set; }
public int? LatestStatusUpdateID { get; set; }
public TrackingTagStatusUpdate LatestStatusUpdate { get; set; }
}
LatestStatusUpdate is optional, as it may not be set if there are not yet any Status Updates for the Tag.
Entity Framework Core complains that "The child/dependent side could not be determined for the one-to-one relationship between 'TrackingTag.LatestStatusUpdate' and 'TrackingTagStatusUpdate.TrackingTag'.". I then add
modelBuilder.Entity<TrackingTag>().HasOne(x => x.LatestStatusUpdate).WithOne(x => x.TrackingTag).HasForeignKey<TrackingTagStatusUpdate>(x => x.TrackingTagID);
to OnModelCreating(ModelBuilder modelBuilder), however this results in Entity Framework Core creating a relationship with a Unique constraint, which will not work as there will be many TrackingTagStatusUpdate with the same TrackingTagID.
How do I do this correctly?
This seems to have worked:
public class TrackingTag
{
public int ID { get; set; }
[ForeignKey(nameof(LatestStatusUpdate))]
public int? LatestStatusUpdateID { get; set; }
public TrackingTagStatusUpdate LatestStatusUpdate { get; set; }
}
I'm not sure how to achieve the same with the Fluent API though.

Entity Type has no key defined error while using fluent mapping Entity Framework

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

MVC One to one relationship with codefirst

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

Join 3 tables using Entity Framework

How can I build a model using Entity Framework to join 3 tables?
At the moment I have:
public class KeywordAdCategory
{
[Key]
[Column("Keyword_Id", Order = 0)]
public int Keyword_Id { get; set; }
[Key]
[Column("Ad_Id", Order = 1)]
public int Ad_Id { get; set; }
[Key]
[Column("Category_Id", Order = 2)]
public int Category_Id { get; set; }
}
But I don't have any navigation properties.
Is there a better way to build a relashionship between 3 tables using Entity Framework?
Also the Keyword, Ad and Category models:
public class Keyword
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
}
public class Ad
{
// Primary properties
[Key]
public int Id { get; set; }
// Navigation properties
public AdOperation AdOperation { get; set; }
public Member Member { get; set; }
public Address Address { get; set; }
public Category Category { get; set; }
public virtual ICollection<Picture> Pictures { get; set; }
private ICollection<Feature> _features;
public virtual ICollection<Feature> Features
{
get { return _features ?? (_features = new HashSet<Feature>()); }
set { _features = value; }
}
}
public class Category
{
// Primary properties
public int Id { get; set; }
public int? CategoryParent_Id { get; set; }
public int? CategoryGroup_Id { get; set; }
public bool IsActive { get; set; }
// Navigation properties
public Keyword Keyword { get; set; }
}
Thanks.
I'm assuming that you're using Code-First Entity Framework here, and that you have your KeywordAdCategory object in your database as well. In which case, just simply do the following in your KeywordAdCategory class to do the proper mapping:
[Key, ForeignKey("Keyword")]
[Column("Keyword_Id", Order = 0)]
public int Keyword_Id { get; set; }
[Key, ForeignKey("Ad")]
[Column("Ad_Id", Order = 1)]
public int Ad_Id { get; set; }
[Key, ForeignKey("Category")]
[Column("Category_Id", Order = 2)]
public int Category_Id { get; set; }
public virtual Keyword Keyword { get; set; }
public virtual Ad Ad { get; set; }
public virtual Category Category { get; set; }
Doing this should do the proper mappings, put FKs on your KeywordAdCategory table, and thus give you the ability to have good navigation properties to the other objects.

One to many in Entity Framework using fluent mapping

Im trying to do a one-to-many map by using fluent api.
This is my classes
public class Product : EntityBase
{
public Product()
{
this.ProductArticles = new List<ProductArticle>();
}
[Key]
public int ProductId { get; set; }
public string Description { get; set; }
public string ReportText1 { get; set; }
public string ReportText2 { get; set; }
public bool Standard { get; set; }
public int ProductGroupId { get; set; }
public decimal? Surcharge1 { get; set; }
public decimal? Surcharge2 { get; set; }
public decimal? Surcharge3 { get; set; }
public decimal? Surcharge4 { get; set; }
public decimal PriceIn { get; set; }
public decimal PriceOut { get; set; }
public decimal PriceArtisanIn { get; set; }
public decimal PriceArtisanOut { get; set; }
public decimal PriceTotalIn { get; set; }
public decimal PriceTotalOut { get; set; }
public decimal PriceTotalOutVat { get; set; }
public decimal PriceAdjustment { get; set; }
public bool Calculate { get; set; }
public string Notes { get; set; }
[ForeignKey("ProductGroupId")]
public virtual ProductGroup ProductGroup { get; set; }
public virtual ICollection<ProductArticle> ProductArticles { get; set; }
}
public class ProductArticle : EntityBase
{
[Key]
public int ProductArticleId { get; set; }
public int ProductId { get; set; }
public int ArticleId { get; set; }
public decimal Qty { get; set; }
public decimal PriceIn { get; set; }
public bool Primary { get; set; }
public virtual Product Product { get; set; }
public virtual Article Article { get; set; }
}
Now i want from single Product include all ProductArticles
This is my mapping
public class ProductMap : EntityTypeConfiguration<Product>
{
public ProductMap()
{
// Primary Key
this.HasKey(p => p.ProductId);
// Table & Column Mappings
this.ToTable("Product");
this.HasMany(p => p.ProductArticles)
.WithOptional()
.Map(p => p.MapKey("ProductId").ToTable("ProductArticle"));
}
But it doesnt work.. Please help :)
First - by convention EF treats property with name equal to Id or EntityTypeName + Id is a primary key. So, you don't need to configure that manually.
Second - if you don't want table names to be plural, just remove that convention from your context instead of providing table name for each entity mapping:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
}
And last - EF smart enough to define foreign keys which have names like RelatedEntityTypeName + Id. So, you don't need any fluent configurations here.

Categories