I have a Database First approach to my application and Entity Framework. I have a base class that many other classes inherit. I am trying to save the class to my EF database, however, I keep getting an error that there is no Discriminator column.
System.Data.SqlClient.SqlException: Invalid column name 'Discriminator'.
Since I am using Database First, how do I manually create this column in my table? I cannot seem to find the datatype of it anywhere.
The entity framework would try to check for the column in all of the derived classes (isn't that what inheritance is all about?). You can try adding [NotMapped] attribute to your child classes.
[NotMapped]
public class ChildClass : ParentClass {
// other stuff here
}
This would minimize your problem. This attribute tells Entity framework which of the properties (if applied to fields) or classes do not need to be mapped. Read more about it: https://msdn.microsoft.com/en-us/data/jj591583.aspx?f=255&MSPPError=-2147217396#NotMapped
Related
The entity model I'm working on is structured with inheritence as per:
public abstract class Line {}
public class WooLine : Line{
public bool wooProperty{ get; set; }
}
public class BooLine : Line
These are both stored in the database in the table Line. And in the database the column wooProperty is NOT NULL and default value (0).
These are maintained in a web app written with Knockout & Breeze. When working with BooLine trying to create a new entity, it throws an exception that I can't insert NULL into column wooProperty.
I set up a profile to trace the query, and it appears that since it's mapped to the Line table, during the Insert EntityFramework reads up all the properties and tries to actually insert NULL into the wooProperty, since it's not present in the Boo model. I'm moderately upset that EF is actively trying to insert NULL to a property I'm not working with...
Anyway. I can't move the wooProperty to the Line model - it belongs in the WooLine model. I'm hoping to solve it by either modifying the metadata in Breeze or forcing the wooProperty onto the saveChanges data. But I can't get breeze to recognize the property in the metadata. I've tried to run
metadataStore.registerEntityTypeCtor(
'BooLine', function () {
this.wooProperty = false;
});
Which almost works - but Breeze maps it as __unmapped value and as such isn't recognized after being recieved by EntityFramework.
I also started playing around with overriding the EFContextProvider and overriding BeforeSaveEntity. Entity is ReadOnly of type BooLine, and I can clearly see WooProperty in the UnmappedProperties, but I have no idea where to go from there... Any ideas?
TLDR in a way; Want to 'trick' entity framework into thinking an unmapped value is mapped when creating an entity.
To summarize my comments I would recommend one of the following:
make your model use TPT inheritance so there is no wooProperty column in the Line table, but in the inherited WooLine table
change your wooProperty column to be nullable and mark the wooProperty property in your entity class as [Required] and let EF take care of reading only "valid WooLines" - this should work if there is also a valid discriminator column for EF to use
I have my database with table names starting with "tbl" prefix and column names like "ua_id" which are understandable in context of project but problematic if used in a model i.e names should be readable or meaningful(not like indicative names defined in database).
So I want to map them in my onmodelcreating method but I have no idea about it. I studied it in following blog:
http://weblogs.asp.net/scottgu/entity-framework-4-code-first-custom-database-schema-mapping
but this is for EF 4.1 and method doesn't work for EF 6.(mapsingletype method)
I want to map my tables by columns to my model as I can't change the column names. I just want the newer version of that syntax in the blog.
Thank You.
If you are using Code First, you can simply decorate your model with Table and Column attribute and give it the database names.
[Table("tbl_Student")]
public class Student
{
[Column("u_id")]
public int ID { get; set; }
}
These attributes are available in the System.ComponentModel.DataAnnotations.Schema namespace
You can keep following inside OnModelCreating
modelBuilder.Entity<MyModel>()
.Property(e => e.MyColumn).HasColumnName("DBColumn")
And if you're not using code-first, just select a table in the model diagram, hit F4 (properties) and change the name.
I have created an entity data model and generated a database from it.
One of the entities is called Template.
Created partial classes to extend the functionality of Template works fine.
If I create a new class and try to derive from Template, I get a runtime exception upon instantiating:
Mapping and metadata information could not be found for EntityType 'Template001'.
How can I work around this? I definitely need to inherit from the EF classes.
EDIT
Does not seem possible. If that is the case, what would be the best way to implement the following requirement: The template entity stores information about templates that each have their own code to execute. That is why I was trying to derive from the entity in the first place.
It is not supported. You cannot derive a new type from entity and use it instead of the mapped entity type for persistence. If you want to have derived class from entity you must use mapped inheritance where every child is also mapped to the database.
Why do you need to inherit from entity class first of all? If you want to add some simple behavior, use partial class.
Update: Based on comments, it appears that there is possibility that behavior will be extended over the time. In this case, I would recommend using composition/aggregation, not inheritance. Let the classes that need to be extended have an entity as a field. In Raheel's scenario, it would be a class called TemplateLogic with field/property of type Template.
I have already created a database using EF Code First. I have implemented a TPH in my model classes. I mean, there is a Person class which is the parent of the Customer class. When I attempted to create the DB at first, only one table named Persons has created that includes a column named Discriminator, just as expected.
Now I am wondering how that column is disappeared!!I've recreated the DB but still no Discriminator filed is there! Does it make any trouble if I make the column directly in the SQL Server? What is the best solution for that?
I really don't know why it disappeared!!!
Thanks in advance
make discriminator a public property get/set if want to see it on the DB
public discriminator {get; set;} // consider virtual if want change tracking proxy
I'm using entity framework code first to create my tables. Please note - create the tables, not the DB, since I'm working on a hosted environment and I don't have a user that is allowed to create db's.
Committing a DB update works fine, but retrieving data gives the exception:
Exception Details: System.Data.SqlClient.SqlException: Invalid object name 'dbo.EventHosts'.
I've read that it happens because I'm not using EF Code First to create the DB. That's fine, but how do I elegantly solve this?
All the generated tables do not have a prefix like dbo. A solution like this doesn't work, and isn't elegant at all:
[Table("EventHosts", Schema = "")]
Ok, for me issue was that I had a table called dbo.UserState and in C# EF was trying to access dbo.UserStates because of pluralization.
The solution was to put Table attribute above class and specify the exact table name:
[Table("UserState")]
public class UserState
{
[Key]
public int UserId { get; set; }
}
To answer your first question: use the schema created for you by your hosting provider.
To answer your second question: No there is currently no direct way to change the default schema globally because you cannot modify existing conventions or create new conventions. You can try to hack it.
For example you can override OnModelCreating and use reflection to get all DbSet<> properties declared in your context. Than you can just use simple loop on these properties and create ToTable mapping call with name of the property as table name and your custom schema. It will require some playing with reflection to make this work.
Alternatively you can try to do some reusable approach by implementing custom conventions. You can find many different articles about using your own conventions with EF. Some examples:
Custom Conventions in Entity Framework Code First v 4.1
Conventions in Entity Framework 4.1 Final
My high level untested idea is following same principle and create assembly level attribute which will be processed by the convention mechanism and applied on all your entities.
Try to set default schema name to 'dbo' in SQL SERVER.
http://msdn.microsoft.com/en-us/library/ms173423.aspx
On of the reason for this error is the table named "EventHosts" may not Exist or that table is renamed to some other name please check with that..
https://stackoverflow.com/a/12808316/3069271
I had same issue, it was pluralize problem between mapping and db.