Insert/Add new entity with nested children entities to DB using Entity Framework Core - entity-framework

Here are Entities:
public class Entity
{
public int Id { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime? ModifiedOn { get; set; }
}
public class EntityBase : Entity
{
[ForeignKey("CreatedBy")]
public int CreatedById { get; set; }
public User CreatedBy { get; set; }
[ForeignKey("ModifiedBy")]
public int? ModifiedById { get; set; }
public User ModifiedBy { get; set; }
}
public class ProjectRequest : EntityBase
{
public string RequestTitle { get; set; }
public string RequestType { get; set; }
...
public virtual ICollection<Material> Materials { get; set; }
public virtual ICollection<Translation> Translations { get; set; }
}
public class Material : EntityBase
{
[ForeignKey("ProjectRequest")]
public int ProjectRequestId { get; set; }
public virtual ProjectRequest ProjectRequest { get; set; }
...
public virtual ICollection<Translation> Translations { get; set; }
}
public class Translation:EntityBase
{
[ForeignKey("ProjectRequest")]
public int ProjectRequestId { get; set; }
public virtual ProjectRequest ProjectRequest { get; set; }
[ForeignKey("Material")]
public int MaterialId { get; set; }
public virtual Material Material { get; set; }
public string ProductMasterText { get; set; }
[MaxLength(40)]
public string ShortDescription { get; set; }
public string MasterDescriptionLine1 { get; set; }
public string MasterDescriptionLine2 { get; set; }
public string MasterDescriptionLine3 { get; set; }
public string LanguageCode { get; set; }
}
No modifications has been done to these entities using fluent API.
Now, whenever I try to insert object of type ProjectRequest with Materials and Translations nested in it, in Translation objects ProjectRequestId is set to 0.
Following is sample Change Tracker snapshot:
Can anyone help me on this? Why ProjectRequestId is 0 but MaterialId properly assigned in Transaltion objects?

Related

Code first one-to-many relationship with restraints

I have the following one-to-many database structure generated by code first. Many Buttons can be added with a relation back to a single GSMUnit. BtnNo should be unique (for every GSMUnitId), and shouldn't be duplicated. Currently it is possible to duplicate. how can i prevent this?
public class GSMUnit
{
public int Id { get; set; }
[MaxLength(20)]
public string Model { get; set; }
[MaxLength(40)]
public string GsmName { get; set; }
[MaxLength(40)]
public string TelephoneNum { get; set; }
public int GSMSiteId { get; set; }
public virtual GSMSite GSMSite { get; set; }
public virtual GSMSetting GSMSettings { get; set; }
public virtual ICollection<Button> Buttons { get; set; }
}
public class Button
{
public int Id { get; set; }
[MaxLength(30)]
public string Primary { get; set; }
[MaxLength(30)]
public string Divert1 { get; set; }
[MaxLength(30)]
public string Divert2 { get; set; }
[MaxLength(30)]
public string Divert3 { get; set; }
[MaxLength(20)]
public string AptNo { get; set; }
[MaxLength(10)]
public string Code { get; set; }
[MaxLength(4)]
public string DTO { get; set; }
[MaxLength(4)]
public string Timeband { get; set; }
[MaxLength(15)]
public string BtnNo { get; set; }
[MaxLength(20)]
public string AptName { get; set; }
public int GSMUnitId { get; set; }
public virtual GSMUnit GSMUnit { get; set; }
}
You can use the Index attribute for that:
public class Button
{
public int Id { get; set; }
[MaxLength(30)]
public string Primary { get; set; }
[MaxLength(30)]
public string Divert1 { get; set; }
[MaxLength(30)]
public string Divert2 { get; set; }
[MaxLength(30)]
public string Divert3 { get; set; }
[MaxLength(20)]
public string AptNo { get; set; }
[MaxLength(10)]
public string Code { get; set; }
[MaxLength(4)]
public string DTO { get; set; }
[MaxLength(4)]
public string Timeband { get; set; }
[MaxLength(15)]
public string BtnNo { get; set; }
[MaxLength(20)]
public string AptName { get; set; }
[Index(IsUnique = true)]
public int GSMUnitId { get; set; }
public virtual GSMUnit GSMUnit { get; set; }
}
But I recommend you to take a look on Fluent API. It's easier to configure in my opinion.

EF code first model not in sync with database

My EF Code First model for some reason is not in sync with the db. I'm getting this error:
{"Invalid column name 'Type_Id1'."}
The field is actually called 'Type_Id' so I'm not sure from where that 1 comes up. I have the table column called as Type_Id and also I've added a Type_Id in my type entity model.
Why might I be getting that error message, plus why I'm getting 1 at the end of the name?
Update
My Task class:
public class Task
{
public Task()
{
Language = 1;
Grades = new HashSet<Grade>();
Categories = new HashSet<Category>();
Subjects = new HashSet<Subject>();
Rooms = new Collection<Room>();
Tools = new Collection<Tool>();
}
[Key]
public int Id { get; set; }
public string Description { get; set; }
public virtual TaskType Type { get; set; }
public string Rules { get; set; }
[Required]
[StringLength(200), MinLength(1)]
public string Name { get; set; }
public int PreperationTime { get; set; }
public int InstructionTime { get; set; }
public int TaskTime { get; set; }
public int Type_Id { get; set; }
public string VideoLink { get; set; }
[Required]
public int Language { get; set; }
public int? MinimumParticipants { get; set; }
public int? MaximumParticipants { get; set; }
public int? Rating { get; set; }
[Required]
public string CreatedBy { get; set; }
public virtual ICollection<Grade> Grades { get; set; }
public virtual ICollection<Category> Categories { get; set; }
public virtual ICollection<Subject> Subjects { get; set; }
public virtual ICollection<Room> Rooms { get; set; }
public virtual ICollection<Tool> Tools { get; set; }
}
DBContext class:
public ApplicationDbContext() : base("DefaultConnection", false)
{
}
public DbSet<Task> Tasks { get; set; }
public DbSet<TaskType> TaskTypes { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
You need to add the FK attribute on your navigation property. EF is creating Type_Id1 because Type_Id already exists (although it can't tell by convention it is the FK).
[ForeignKey("Type_Id")]
public virtual TaskType Type { get; set; }
https://msdn.microsoft.com/en-us/data/jj591583.aspx#Relationships

Entity Framework Code first adds unwanted foreign key column

I have a many to one relationship between Categories and News.
The problem I'm having is that EF keeps adding a foreign key colum to my table which I dont want!
News class
public class News
{
public News()
{
}
[Key]
public int NewsID { get; set; }
public int PublishedByID { get; set; }
public string PublishedByFullName { get; set; }
public string PublishedByEmail { get; set; }
public DateTime DatePublished { get; set; }
public string Title { get; set; }
public string PreviewText { get; set; }
public string BlobName { get; set; }
public virtual Category Category { get; set; }
}
Categories class
public class Category
{
public Category()
{
News = new HashSet<News>();
}
[Key]
public int CategoryID { get; set; }
public string Name { get; set; }
public string CategoryTypeName { get; set; }
public virtual ICollection<News> News { get; set; }
}
Database
My question
How do I remove Category_CategoryID in News table?
I'm guessing i'm missing some code in my OnModelCreating method.
You need to add id field in News class to reference Category.
public class News
{
[Key]
public int NewsID { get; set; }
public int CategoryID { get; set; } // added
public int PublishedByID { get; set; }
public string PublishedByFullName { get; set; }
public string PublishedByEmail { get; set; }
public DateTime DatePublished { get; set; }
public string Title { get; set; }
public string PreviewText { get; set; }
public string BlobName { get; set; }
public virtual Category Category { get; set; }
}

Entity Framework [Key] tag not being recognised

I am getting warning errors of no key having been defined for each of my class library classes despite the fact that I have the [Key] tag and including the System.ComponentModel.DataAnnotations namespace, here is my context:
Context:
namespace Project.Data
{
public class ProjectContext : DbContext, IProjectContext
{
public ProjectContext(string connString)
: base(connString)
{
this.Configuration.LazyLoadingEnabled = true;
Database.SetInitializer<ProjectContext>(new ProjectInitializer());
this.Database.CreateIfNotExists();
this.Database.Initialize(true);
}
public IDbSet<Article> Article { get; set; }
public IDbSet<Brand> Brand { get; set; }
public IDbSet<Colour> Colour { get; set; }
public IDbSet<Customer> Customer { get; set; }
public IDbSet<CustomerCredit> CustomerCredit { get; set; }
public IDbSet<Delivery> Delivery { get; set; }
public IDbSet<DesignerTicket> DesignerTicket { get; set; }
public IDbSet<EuroRate> EuroRate { get; set; }
public IDbSet<Gift> Gift { get; set; }
public IDbSet<GZero> GZero { get; set; }
public IDbSet<InvoiceStock> InvoiceStock { get; set; }
public IDbSet<PrintOptions> PrintOptions { get; set; }
public IDbSet<Product> Product { get; set; }
public IDbSet<ProductLocation> ProductLocation { get; set; }
public IDbSet<Sale> Sale { get; set; }
public IDbSet<SaleAccount> SaleAccount { get; set; }
public IDbSet<SalesToWeb> SalesToWeb { get; set; }
public IDbSet<Shop> Shop { get; set; }
public IDbSet<Staff> Staff { get; set; }
public IDbSet<Ticket> Ticket { get; set; }
public IDbSet<Transfer> Transfer { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
}
Context Interface:
namespace Project.Data
{
public interface IProjectContext
{
IDbSet<Article> Article { get; set; }
IDbSet<Brand> Brand { get; set; }
IDbSet<Colour> Colour { get; set; }
IDbSet<Customer> Customer { get; set; }
IDbSet<CustomerCredit> CustomerCredit { get; set; }
IDbSet<Delivery> Delivery { get; set; }
IDbSet<DesignerTicket> DesignerTicket { get; set; }
IDbSet<EuroRate> EuroRate { get; set; }
IDbSet<Gift> Gift { get; set; }
IDbSet<GZero> GZero { get; set; }
IDbSet<InvoiceStock> InvoiceStock { get; set; }
IDbSet<PrintOptions> PrintOptions { get; set; }
IDbSet<Product> Product { get; set; }
IDbSet<ProductLocation> ProductLocation { get; set; }
IDbSet<Sale> Sale { get; set; }
IDbSet<SaleAccount> SaleAccount { get; set; }
IDbSet<SalesToWeb> SalesToWeb { get; set; }
IDbSet<Shop> Shop { get; set; }
IDbSet<Staff> Staff { get; set; }
IDbSet<Ticket> Ticket { get; set; }
IDbSet<Transfer> Transfer { get; set; }
}
}
[Key] decorated class example:
namespace Project.Data
{
public class Article
{
[Key]
public int ArticleID;
public bool IsCore;
public string Make;
public string Product;
public decimal Sale;
public string Department;
public string Scale;
public string Detail;
public DateTime InDate;
public decimal Reduce;
public bool IsOnSale;
public string VAT;
public bool IsOnWeb;
public string ProductCode;
public string Pick;
public string MemoDetail;
public string LOC;
public string ColourCode;
public bool StatusFlag;
public string Terminal;
}
}
Despite have the [Key] placed on Article I am getting the following message for the article class as shown below and this is repeated for each of the classes:
Project.Data.Article: : EntityType 'Article' has no key defined. Define the key for this EntityType.
Anyone see what I am doing wrong here? would be greatly appreciated
Define the members of your class as public properties as opposed to public variables like you have here, by including {get; set;} at the end of the declaration

Code first fluent api - table relationship

I have following tables and need to set relationship between them.
Model classes for the tables are as given
public class UserAction
{
public int ActionID { get; set; }
public string ActionName { get; set; }
public virtual ICollection<RoleScreenActionPermission> RoleScreenActionPermissions { get; set; }
}
public class Screen
{
public int ScreenID { get; set; }
public string ScreenName { get; set; }
public virtual ICollection<RoleScreenActionPermission> RoleScreenActionPermissions { get; set; }
}
public class ScreenAction
{
public int ScreenActionID { get; set; }
public int ScreenID { get; set; }
public int ActionID { get; set; }
public virtual Screen Screen { get; set; }
public virtual UserAction UserAction { get; set; }
}
public class RoleScreenActionPermission
{
public int RoleScreenActionPermissionID { get; set; }
public int ScreenActionID { get; set; }
public int RoleID { get; set; }
public virtual ScreenAction ScreenAction { get; set; }
public virtual Role Role { get; set; }
}
The talbe structure created is as:
Please help with setting the relationship correctly.
Try to remove all your own foreign keys from your classes. EF must make it.
upd:
public class Screen
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Action
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ScreenAction
{
public int Id { get; set; }
public virtual Screen Screen { get; set; }
public virtual Action Action { get; set; }
}
public class RoleScreenActionPermission
{
public int Id { get; set; }
public virtual ScreenAction ScreenAction { get; set; }
public virtual Role Role { get; set; }
}