ASPNET MVC5 web application.
Model
public partial class Product
{
public int? ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsDeleted { get; set; }
public bool IsApproved { get; set; }
public int CategoryID { get; set; }
public virtual Category Category { get; set; }
public virtual AspNetUsers User { get; set; }
I need to modify this model (working since ever) by including a new virtual property.
public virtual category_trans CategoryTrans { get; set; }
based on model:
public class category_trans
{
[Key]
[Column(Order = 1)]
public int category_id { get; set; }
[Key]
[Column(Order = 2)]
public int language_id { get; set; }
public string name { get; set; }
}
Please note this table has a composite PK. This is the only apparent difference with the other virtual categories successfully implemented in Product model class up to now.
category_trans model class works just fine in many queries as defined but, as I introduce the new virtual CategoryTrans in Product model, without even referencing it in any query , i get following error:
System.Data.Entity.Core.EntityCommandExecutionException: An error occurred while executing the command definition. See the inner exception for details. ---> System.Data.SqlClient.SqlException: Invalid column name 'category_trans_category_id'. Invalid column name 'category_trans_language_id'. in System.Data.SqlClient.SqlCommand.<>c.b__174_0(Task
1 result) in System.Threading.Tasks.ContinuationResultTaskFromResultTask
2.InnerInvoke() in System.Threading.Tasks.Task.Execute()
Modify your Product
Model as follows :
public partial class Product{
public int? ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsDeleted { get; set; }
public bool IsApproved { get; set; }
[ForeignKey("CategoryTrans"), Column(Order = 1)]
public int Cat_ID { get; set; }
[ForeignKey("CategoryTrans"), Column(Order = 2)]
public int Lang_ID { get; set; }
public virtual Category Category { get; set; }
public virtual AspNetUsers User { get; set; }
public virtual category_trans CategoryTrans { get; set; }
}
This will work..
EDIT
T_SQL script of the created table given below
CREATE TABLE [dbo].[Products] (
[Cat_ID] INT NOT NULL,
[Lang_ID] INT NOT NULL,
[ID] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (MAX) NULL,
[Description] NVARCHAR (MAX) NULL,
[IsDeleted] BIT NOT NULL,
[IsApproved] BIT NOT NULL,
CONSTRAINT [PK_dbo.Products] PRIMARY KEY CLUSTERED ([ID] ASC),
CONSTRAINT [FK_dbo.Products_dbo.category_trans_Cat_ID_Lang_ID] FOREIGN KEY ([Cat_ID], [Lang_ID]) REFERENCES [dbo].[category_trans] ([category_id], [language_id]) ON DELETE CASCADE);
GO
CREATE NONCLUSTERED INDEX [IX_Cat_ID_Lang_ID]
ON [dbo].[Products]([Cat_ID] ASC, [Langu_ID] ASC);
The translation for the categories belong to the category itself and not to the product. So I recommend to add that to the category.
Model classes
public class Language
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsDeleted { get; set; }
public bool IsApproved { get; set; }
public int CategoryId { get; set; }
public virtual Category Category { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<CategoryTrans> Translations { get; set; }
}
public class CategoryTrans
{
public int CategoryId { get; set; }
public virtual Category Category { get; set; }
public int LanguageId { get; set; }
public virtual Language Language { get; set; }
public string Name { get; set; }
}
Definition of the relation with FluentAPI
public class Model1 : DbContext
{
public Model1()
: base( "name=Model1" )
{
}
protected override void OnModelCreating( DbModelBuilder modelBuilder )
{
base.OnModelCreating( modelBuilder );
var language = modelBuilder.Entity<Language>();
language.HasKey( e => e.Id );
language.Property( e => e.Name ).IsRequired().HasMaxLength( 100 );
var product = modelBuilder.Entity<Product>();
product.HasKey( e => e.Id );
product.Property( e => e.Name ).IsRequired().HasMaxLength( 100 );
product.Property( e => e.Description ).IsOptional().HasMaxLength( 1000 );
product.Property( e => e.IsDeleted ).IsRequired();
product.Property( e => e.IsApproved ).IsRequired();
product.HasRequired( e => e.Category )
.WithMany()
.HasForeignKey( e => e.CategoryId )
.WillCascadeOnDelete( false );
var category = modelBuilder.Entity<Category>();
category.HasKey( e => e.Id );
category.Property( e => e.Name ).IsRequired().HasMaxLength( 100 );
category.HasMany( e => e.Translations )
.WithRequired( e => e.Category )
.HasForeignKey( e => e.CategoryId )
.WillCascadeOnDelete( true );
var categoryTrans = modelBuilder.Entity<CategoryTrans>();
// composite key
categoryTrans.HasKey( e => new { e.CategoryId, e.LanguageId } );
categoryTrans.HasRequired( e => e.Language )
.WithMany()
.HasForeignKey( e => e.LanguageId )
.WillCascadeOnDelete( false );
}
}
And the resulting migration
public partial class InitialCreate : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.Languages",
c => new
{
Id = c.Int(nullable: false, identity: true),
Name = c.String(nullable: false, maxLength: 100),
})
.PrimaryKey(t => t.Id);
CreateTable(
"dbo.Products",
c => new
{
Id = c.Int(nullable: false, identity: true),
Name = c.String(nullable: false, maxLength: 100),
Description = c.String(maxLength: 1000),
IsDeleted = c.Boolean(nullable: false),
IsApproved = c.Boolean(nullable: false),
CategoryId = c.Int(nullable: false),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.Categories", t => t.CategoryId)
.Index(t => t.CategoryId);
CreateTable(
"dbo.Categories",
c => new
{
Id = c.Int(nullable: false, identity: true),
Name = c.String(nullable: false, maxLength: 100),
})
.PrimaryKey(t => t.Id);
CreateTable(
"dbo.CategoryTrans",
c => new
{
CategoryId = c.Int(nullable: false),
LanguageId = c.Int(nullable: false),
Name = c.String(),
})
.PrimaryKey(t => new { t.CategoryId, t.LanguageId })
.ForeignKey("dbo.Languages", t => t.LanguageId)
.ForeignKey("dbo.Categories", t => t.CategoryId, cascadeDelete: true)
.Index(t => t.CategoryId)
.Index(t => t.LanguageId);
}
public override void Down()
{
DropForeignKey("dbo.Products", "CategoryId", "dbo.Categories");
DropForeignKey("dbo.CategoryTrans", "CategoryId", "dbo.Categories");
DropForeignKey("dbo.CategoryTrans", "LanguageId", "dbo.Languages");
DropIndex("dbo.CategoryTrans", new[] { "LanguageId" });
DropIndex("dbo.CategoryTrans", new[] { "CategoryId" });
DropIndex("dbo.Products", new[] { "CategoryId" });
DropTable("dbo.CategoryTrans");
DropTable("dbo.Categories");
DropTable("dbo.Products");
DropTable("dbo.Languages");
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.