What causes Entity Framework to create a table for a base class? - entity-framework-migrations

I keep falling into the trap of declaring an abstract base class for my tables and then finding that the base class is created by the data migration.
I know not to create a DBSet in the context for the table I don't want
The following class does not cause a BasicBo table to create
public abstract class BasicBo : IXafEntityObject //, IObjectSpaceLink we should just declare it when we really need it... mainly we want out business objects to be like POCOs
{
[Browsable(false)]
[Key]
public virtual int Id { get; set; }
public virtual void OnCreated()
{
}
public virtual void OnSaving()
{
}
public virtual void OnLoaded()
{
}
}
However this class does cause a BasicNodeBo table to be created
public abstract class BasicNodeBo : IXafEntityObject
{
[Browsable(false)]
[Key]
public virtual int Id { get; set; }
public virtual int SiblingOrder { get; set; }
public virtual string Sequence { get; set; }
public virtual void RecalculateSequence()
{
}
public virtual void AddDependency(IObjectSpace os, BasicNodeBo sibling)
{
}
public virtual void OnCreated()
{
}
public virtual void OnSaving()
{
}
public virtual void OnLoaded()
{
}
}

I think it may be the presence of BasicNodeBo as a persistant navigation property in a business object..

Related

How to use table created using TPH in entity framework?

Domain Model
public abstract class BaseClass
{
public int Id { get; set; }
public int Something1 { get; set; }
public int Something2 { get; set; }
public string Something3 { get; set; }
}
public class PQR1 : BaseClass
{
public int value1 { get; set; }
}
public class PQR2 : BaseClass
{
public int value2 { get; set; }
}
public class PQR3 : BaseClass
{
public int value2 { get; set; }
}
Context Class
public class PQRContext : DbContext
{
public PQRContext() : base ("PQR")
{
}
public DbSet<BaseClass> Baseclass { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<BaseClass>().
Map<PQR1>(m => m.Requires("Type").HasValue("Value1"))
.Map<PQR2>(m => m.Requires("Type").HasValue("Value2"))
.Map<PQR3>(m => m.Requires("Type").HasValue("Value3"));
}
}
It'll create table like this:
But I don't know how to use this table while coding, I get stuck like this
So I can't access to another classes like PQR1, PQR2,PQR3 where as I have no reason to insert data into base class which is already abstract.
First option :
You are not restricted on DbSet creations. You can create many DbSet as much as you need for your derived classes like the code below and access them like you will do with other DbSet :
public DbSet<BaseClass> Baseclass { get; set; }
public DbSet<PQR1> PQR1s { get; set; }
public DbSet<PQR2> PQR2s { get; set; }
public DbSet<PQR3> PQR3s { get; set; }
You use the DbSet related to the derived you want for inserting into or requesting your context.
Second option :
For querying your context and get only the desired subclass entities you can use the generic method OfType<T> which act as a filter like this:
var myBaseClassList = myContext.BaseClass; // Retrieve all PQR1, PQR2 and PQR3 entities
var myPQR1List = myContext.BaseClass.OfType<PQR1>(); // Retrieve all PQR1
var myPQR2List = myContext.BaseClass.OfType<PQR2>(); // Retrieve all PQR2
var myPQR3List = myContext.BaseClass.OfType<PQR3>(); // Retrieve all PQR3
For inserting you can create an instance of your derived class and add it directly to your base class DbSet :
var pqr1 = new PQR1() { /* set my properties */ };
myCOntext.BaseClass.Add(pqr1); // EF knows how to insert data for classes that use TPH.

Table name in data annotations in entity framework doesn't work.

I create a project in MVC 5 with entity framework 6. I am using code first approach. I want in one of the models define a different name for the table then the default. For that I use the System.ComponentModel.DataAnnotationsname space and define the class like this:
[Table(Name="Auditoria")]
public class AuditoriaDAL
{
[Key]
public int AuditoriaId { get; set; }
...
}
Running the project I get a database with a table with the name AuditoriaDALs. Why the table have this name a not the name that I define?
You are referencing the System.Data.Linq.Mapping.Table attribute when you need to reference System.ComponentModel.DataAnnotations.Schema.Table. So either do this:
[System.ComponentModel.DataAnnotations.Schema.Table("Auditoria")]
public class AuditoriaDAL
{
[Key]
public int AuditoriaId { get; set; }
...
}
Or better yet:
using System.ComponentModel.DataAnnotations.Schema;
...
[Table("Auditoria")]
public class AuditoriaDAL
{
[Key]
public int AuditoriaId { get; set; }
...
}
https://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations(v=vs.110).aspx
you can set TableName like below :
public class MyContext : DBContext
{
public virtual DbSet<AuditoriaDAL> Auditorias { get; set; }
}
Or in OnModelCreating :
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<AuditoriaDAL>().ToTable("Auditorias");
}
The name= isn't necessary. You should try [Table("Auditoria")].

EF CodeFirst One-to-One

I find thousands examples for codefirst relations, but i can't do work my sample !
Many errors like this:
The ForeignKeyAttribute on property 'LanguageID' on type 'BL.Objects.User' is not valid. The navigation property 'Language' was not found on the dependent type 'BL.Objects.User'. The Name value should be a valid navigation property name.
and same same same...
I really want to load language association with user. (en, ru, es)
public abstract class BaseUser : FinanceBase<int>, IUser
{
[ForeignKey("Language")]
public int LanguageID { get; set; }
[ForeignKey("LanguageID")]
public virtual Language Language { get; private set; }
}
public class User : BaseUser
{
public override void GenerateID()
{
...
}
}
public abstract class BaseLanguage : FinanceBase<int>, ILanguage
{
#region Implementation of ILanguage
public string Code { get; set; }
public string Fullname { get; set; }
public string ImagePath { get; set; }
#endregion
}
public class Language : BaseLanguage
{
public override void GenerateID()
{
}
}
public class FinanceDatabaseContext : DbContext
{
public FinanceDatabaseContext()
{
Database.SetInitializer(new FinanceContextInitializer());
}
public DbSet<User> Users { get; set; }
public DbSet<Language> Languages { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().Map(m =>
{
m.MapInheritedProperties();
m.ToTable("Users");
}).HasKey(x => x.ID).HasRequired(x => x.Language).WithMany().HasForeignKey(x => x.LanguageID);
modelBuilder.Entity<Language>().Map(m =>
{
m.MapInheritedProperties();
m.ToTable("Languages");
}).HasKey(x => x.ID);
base.OnModelCreating(modelBuilder);
}
}
public class FinanceContextInitializer : DropCreateDatabaseIfModelChanges<FinanceDatabaseContext>
{
protected override void Seed(FinanceDatabaseContext context)
{
context.Database.ExecuteSqlCommand("ALTER TABLE Users ADD CONSTRAINT uc_Language UNIQUE(LanguageID)");
}
}
Thanks !
You don't need to use foreign key for LanguageID
public int LanguageID { get; set; }
[ForeignKey("LanguageID ")]
public virtual Language Language { get; private set; }
Add a virtual navigation field to your User table for language if it isnt already there.
Ie you have LanguageId and Language in the POCO class User.
The alternative is a navigation field in Language Class back to User,
ie Public virtual List Users
But lets stick to Users having BOTH virtual navigation property and Foreign Key Id field.
... the rest of User.....
public int LanguageId
// nav relationship
public virtual Language Language { set; get; }
// Now the FK declaration as you described should work in fluent API...
// Has required NAVIGATION property, its 1 to many and the I have a field for this FK value called X
modelBuilder.Entity<User>().Map(m =>
{
m.MapInheritedProperties();
m.ToTable("Users");
}).HasKey(x => x.ID).HasRequired(x => x.Language).WithMany().HasForeignKey(x => x.LanguageID);
Solved. My Navigation property Language has private setter
[ForeignKey("LanguageID")]
public virtual Language Language { get; private set; }

Entity Framework added s to my .dbo

I using "Entity Framework DbContext" at the moment I have got exception towars.dbo was not found. This is very strange because in my website I all the time ask about towar.dbo but no towars.dbo Do you know where is a problem?
- InnerException {"Invalid object name 'dbo.Towars'."} System.Exception {System.Data.SqlClient.SqlException}
My all things about Towar (of course different place in my program):
public class ProductController : Controller
{
//
// GET: /Product/
public ITowarRepository repository;
public ProductController(ITowarRepository productRepository)
{
repository = productRepository;
}
public ViewResult List()
{
return View(repository.Towar);
}
}
public interface ITowarRepository
{
IQueryable<Towar> Towar { get; }
}
public DbSet<Towar> Towar { get; set; }
public class EFTowarRepository : ITowarRepository
{
public EFDbContext context = new EFDbContext();
public IQueryable<Towar> Towar
{
get { return context.Towar; }
}
}
public class Towar
{
[Key]
public int Id_tow { get; set; }
public string Nazwa { get; set; }
public string Opis { get; set; }
public decimal Cena { get; set; }
public int Id_kat { get; set; }
}
Add the following line to your context:
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
You can tell EF to map to the table Towar by overriding the OnModelCreating method in your DBContext class with fluent API like this:
public class EFDbContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Towar>().ToTable("Towar");
}
}
Now EF will look for Towar table instead of Towars. If you do not have these tables created, there is some other problem you are having.
EF Code First automatically pluralizes the table names. Use a [Table] attribute to explicitly map the entity to a table name:
[Table("Towary")]
public class Towary
{
// Whatever properties
}
It looks like there's a way to disable pluralization gobally too, see Entity Framework Code First naming conventions - back to plural table names?.
using System.Data.Entity.ModelConfiguration.Conventions;
namespace MVCDemo.Models
{
public class EmployeeContext : DbContext
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
For the sake of completeness #forty-two

Entity framework code first circular reference

I want an object to reference itself. How do I write this model? For eg.
public class Term
{
public int TermId { get; set; }
public string Name { get; set; }
public virtual Term PreviousTerm { get; set; }
public virtual int? PreviousTermId { get; set; }
}
The schema generated is:
TermId
Name
PreviousTermId
PreviousTerm_TermId
So apparently, PreviousTermId serves no purpose here as a relationship FK.
But when using automapper, I have to map to PreviousTermId, I cant create the new object PreviousTerm and assign the Id to that. How do I fix this?
Try specifying the mappings in onModel OnModelCreating event
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Term>().HasOptional(t =>t.PreviousTerm).WithMany().
HasForeignKey(t=>t.PreviousTermId);
}

Resources