I have a column in the database that cannot be null, and I want to set it to have a default value in the database . The problem is that entity framework seems to create a default value itself (for example, int => 0), and completely ignores the default value constraint in the database.
Is there any way to disable this default valuing of entity framework?
I have found that you can decorate your fields with the following attribute.
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
Natively, Entity framework do not allows this. You have to do some code to it. This answer from another site seems to had solved the problem for many people.
He "hacks" it (as he told) by doing something like that:
public partial class YourEntityClass {
public YourEntityClass() {
this.PropertyNameWithDefaultValue = default(int);
}
}
Note 1 : Someone mention that it may not work in EF4
Personal note : Sorry for my english, I usually speak French.
Sometimes we need to do manually what EF doesn't do automatically for us.
In case using EF 4.1 "Code First", I usually create a separated class DbInitializer derived from IDatabaseInitializer, and in the implementation of the InitializeDatabase method, just call the
context.Database.ExecuteSqlCommand("ALTER TABLE TABLENAME ... ");
Now at the static constructor of the class derived from DbContext, just call the initializer:
Database.SetInitializer(new DbInitializer());
In this way, it's possible to specify any database DML/DDL commands to alter tables/columns just to make sure the DB is like we want.
"Computed" fields in EF are not the same as fields with default values in SQL. A computed field is one that is computed on the server and shouldn't be altered when an object is submitted. If you put a Computed tag on a field, you will get the default when you first create the object, but then you will not be able to change that field later on. So, if you get an entity from the DB make a change to a computed field and then call "saveChanges()" on your entity context, the field will not be altered in the DB.
Better to use EF defaults by setting the Default Value for the attribute in the EDMX editor.
It's a pain in the butt that the EDMX updater can't read the field defaults when there is a one to one mapping between the entity field and the database field.
You can update the EDMX model to change the default value for any column via the Properties window. However, Entity Framework doesn't seem to pickup DEFAULT constraints automatically. Not sure if there is a way to make it do that.
Related
The Microsoft docs for Entity Framework show that you can mark a property of a type as "Value generated on add or update". So in the situation where I want a LastUpdated column to be given the current date when a row is updated, I can mark that property like so:
But as you can see, it gives a warning that EF isn't going to actually make it happen. Following that link in the warning explicitly tells us that if we want a Date column set to the current date whenever a row is updated, we need to go and create the trigger in the database ourselves to make it happen.
So what does it mean, and what is the point of "letting EF know that values are generated for added or updated entities"?
You are reading it incorrectly. It says
It does not guarantee that EF will...
It doesn't say "EF will not do anything with this". If, for example, you are working on Code First, and you set up the PK to
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
EF will actually set up that column with Identity (on SQL Server).
It also means that EF will not send that value on updates and inserts, since the database is supposed to fill those in.
Remember that EF works with many providers, and it's up to each provider to give that possibility, that's why it's not guaranteed.
Well, "does not guarantee" bit is indeed a little vague.
But what you do want is for EF to understand that it should include these columns in a Select but not in an Update or Insert.
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 an nvarchar in a table with the length of 6. I created it with code first and the data notation [StringLength(6)].
I want to change the length to 20. I tried to change it in the code and make a new migration but that did nothing.
I did not find a way to do it with code first. The only way that worked for me was to make a query on the Database direcly.
ALTER TABLE [Tablename] ALTER COLUMN [Columname] nvarchar(20).
I had the concern that this would throw an exception because of the DatabaseContextModelSnapshot file but it worked fine. If you do this approach I would recommend to also make the changes in code and to make a new Migration for it. It is not necessary but that way your migrations & code are consistent with the Database.
One thing you can do,Use Fluent Api to change your column name in onModelCreating() method.
this method can be override in your class where your are inheriting from DbContext class.
I typically work with my DBA to design my database tables before I begin developing. In nearly all instances, I use the varchar datatype for storing strings in my SQL database.
When I use EF Power Tools to generate my model classes, the column names and lengths get generated correctly, but I always have to go back in and specify HasColumnType("varchar"); because by default everything is nvarchar (I know this by looking at the queries EF generates and the sitautions where it needs to CAST() to varchar).
Is there any way I can generate my model classes from my database and have EF know the correct data types (varchar vs nvarchar)? Meaning, is there anyway I can auto generate my C# model class for my varchar(50) column to show as:
this.Property(t => t.MyColumn)
.HasMaxLength(50)
.HasColumnType("varchar");
Thank you.
Sure, in your OnModelCreating method, use this:
modelBuilder.Properties<string>().Configure(c => c.HasColumnType("varchar"));
In case you need to still have some string columns be NVARCHAR, you can just specify that on those specific properties after you use this command. According to Microsoft, FluentAPI operates in a "last wins" manner. So, you can do whatever you want to any property or group of properties, and if you make another change to the same property later, the one specified later will be the final result.
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.