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.
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.
first off, I'm pretty certain that this must have been asked before but have been unable to find an exact answer via googling, so please bear with me.
I have inherited a code first entity framework project which uses migrations. I've added a (non-nullable) column to a table and I need to insert values into this column for all existing entries - which are not the default value:
public override void Up()
{
AddColumn("dbo.QuestionType", "Duplicated", c => c.Boolean(nullable: false, defaultValue: false));
Sql("UPDATE dbo.QuestionType SET Duplicated = 1");
}
However there was originally some seed data added to this table:
context.QuestionTypes.AddOrUpdate(
e => e.Name,
new QuestionType() { Name = QuestionTypeNames.INTERVIEWER});
which means that the update statement is immediately overwritten by the data in the call to the Seed method (called after each migration).
My questions are:
Is it 'safe' to simply add the extra value into the Seed data (or will this cause everything to break for earlier migrations where the new column doesn't exist on the database).
Alternatively is there any way to prevent the Seed method from running after this migration (and all subsequent migrations).
Thanks
Entity Framework is great, but to be able to use it effectively, I'm afraid we really have no choice but to be diligent in making sure that the migrations and the seed method are in sync and work well with each other.
Yes, if you put the new value in the seed (ie. new QuestionType() { Name = QuestionTypeNames.INTERVIEWER, Duplicated = true}), this will cause systems which do not have the latest migration applied to break. This is because the seed method will be looking for the Duplicated column but will not find it.
No, I don't think there is a way to do this, at least not automatically. One solution is this: since you have access to the context object in the seed method, you can just query the database to check if the particular migration already exists. You can then wrap the specific seeder for QuestionTypes in an if statement, utilizing the result of the earlier query.
I am using ASP.NET to build a application for a retail company. I am using the Entity Framework (model-first) as my data access layer. I am using stored procedures to do my CRUD operations and all columns are mapped and seems to be correct as all CRUD functionality are working as expected.
But I am having concurrency issues with the DELETE operation.
I've added a TimeStamp column to the table I am doing the CRUD operation on. The UPDATE operation works fine as it is updating by primary key and the TimeStamp value. Thus if no rows are affected with the UPDATE operation, because of a change in the TimeStamp value, the Entity Framework throws a OptimisticConcurrencyException.
The DELETE operation works on the same principle as it is deleting by primary key and the TimeStamp value. But no exception is thrown when the TimeStamp value does not match between the entity and the database.
In the C# delete method I do retrieve the latest record first and then update the TimeStamp property to another TimeStamp value (It might be different to the retrieved value). After some investigation by using SQL Profiler I can see that the DELETE stored procedure is executed but the TimeStamp parameter that is passed to the stored procedure is the latest TimeStamp value and not the value that I have set the TimeStamp property to. Thus the record is deleted and the Entity Framework does not throw an exception.
Why would the Entity Framework still pass the retrieved TimeStamp value to the Stored Procedure and not the value that I have assigned the property? Is this be design or am I missing something?
Any help will be appreciated! (where is Julie Lerman when you need her! :-))
Optimistic concurrency in EF works fine. Even with stored procedures.
ObjectContext.DeleteObjects passes original values of entity to delete function. This makes sense. Original values are used to identify the row to delete. When you delete object, you don't (usually) have meaningful edits to your entity. What do you expect EF to do with then? Write? To what records?
One legitimate use for passing modified data to delete function is when you want to track deletes in some other table and you need to throw in some information not accessible at database layer, only at business layer. Examples include application level user name or reason to delete. In this situation you need to construct entity with this values as original values. One way to do it:
var x = db.MyTable.Single(k => k.Id == id_to_delete);
x.UserName = logged_in_user;
x.ReasonForChange = some_reason;
// [...]
db.ObjectStateManager.ChangeObjectState(x, EntityState.Unchanged);
db.MyTable.DeleteObject(x);
db.SaveChanges();
Of course, better strategy might be to do it openly in business layer.
I don't understand your use case with rowversion/timestamp.
To avoid concurrency issues you pass original timestamp to modifying code.
That way it can be compared to current value in database to detect if record changed since you last read it.
Comparing it with new value makes little sense.
You usually use change markers that are automatically updated by database like rowversion/timestamp in SQL Server, rowversion in Oracle or xmin in PostgreSQL.
You don't change its value in your code.
Still, if you maintain row version manually, you need to provide:
a) new version to insert and update to be written, and
b) old version (read from database) to update and delete to check for concurrent changes.
You don't send new value to delete. You don't need to.
Also, when using stored procedures for modification, it's better to compute new version in the procedure and return it to application, not the other way around.
Hard to tell without seeing any code, but maybe when the postback occurs the page is being re-bound before your delete method is firing? On whatever method databinds the form controls (I assume it's OnLoad or OnInit), have you wrapped any databinding calls with if ( !this.IsPostBack ) { ... }?
Also I'm not sure if there's a reason why you're explicitly storing the concurrency flag in viewstate/session variables, but a better way to do it (imo) is to add the timestamp to the DataKeyNames property of the FormView/GridView (ie: <asp:FormView ID='blah' runat='server' DataKeyNames='Id, Timestamp'>.
This way you don't have to worry about manually storing or updating the timestamp. ;)
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.
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.