We have a SQL Server 2008 R2 database with several tables and each table has a number of triggers. On one of the columns, we'll call this Person.Age we have a default value, so that if I don't explicitly supply a value it defaults to "18".
create table PERSON
(
id int IDENTITY(1,1) PRIMARY KEY,
age char(2) DEFAULT '18',
Name char(40),
);
I am using EntityFramework 4.0 (and have also tried 5.0) and Visual Studio 2010, to load and select from the database. Whenever I insert into the table using the following statement, it is inserting a row, but it isn't completing the default value:
var person = new Person
{
Name = "Peter"
};
using (var ctx = new MyEntities())
{
ctx.PERSON.AddObject(person);
ctx.SaveChanges();
}
This will result in a row with a Name of Peter, but the Age will be set to null - and not my default of 18.
When I refresh/load my EDMX file I can only seem to import simple tables and views and there doesn't appear to be an option for importing the properties - although I would have thought this was done by default? Any ideas why the default properties aren't firing?
Also, I have triggers defined in SQL Server so that when a new row is inserted into PERSON, an additional table gets updated. Again this works if I run the SQL direct against the database, but doesn't work if I execute through Visual Studio using EntityFramework.
Thanks,
EF will explicitly set the columns to values you passed. Since, when you created a Person entity, the value for age will be by default set to null EF will send a command in which it will set the column value to null. Set the default value in the ctor if you want to have the default value (otherwise the default value is null for reference properties and default(T) for value type properties (e.g. int)).
The EF designer brings all the columns from the database and create a model with entities that have properties coresponding to the values to the tables and columns it reversed engieneered. You can then go and tweak your model in the designer - for instance you can remove properties you don't want.
I don't know what "does not work" means for you in case of the triggers - it probably depends on your expectation. EF just sends a command to the database. So if you send the same Sql command as the EF sends it should "not work" in the same way. Having said that EF is database agnostic and is not aware of DB magic like triggers. Also the communication is one way only from EF to the DB. So, if you expect that the database notifies the EF about something then it will not work. There are no means for doing this.
Related
I have a scenario where I know the primary key of an entity (retrieved from an unrelated source), and I want to update just 1 property (db column). I have NOT already retrieved the entity from the database. If possible I would like to not have to make this extra round trip.
I create the entity using manager.createEntity.
I update one of the properties.
Then set the entityAspect to setModified();
When saving changes, all the properties that were not updated are set to their default values, and the generated SQL UPDATE statement attempts to update all mapped columns.
Is there a way to tell breeze to only generate SQL for specific properties/columns?
thanks
As you discovered, the properties of the originalValuesMap guide the Breeze server's ContextProvider as it prepares the save request. This is documented in the ContextProvider topic.
In your example, you call setModified after you've changed the property. All that does is change the EntityState; it doesn't create an entry in the client entity's entityAspect.originalValuesMap ... therefore the originalValuesMap sent to the server is empty.
I'm a little surprised that the EFContextProvider.SaveChanges prepared an EF update of the entire entity. I would have guessed that it simply ignored the entity all together. I'm making a mental note to investigate that myself. Not saying the behavior is "right" or "wrong".
You do not have to manipulate the originalValuesMap to achieve your goal. Just change the sequence. Try this:
var foo = manager.createEntity('Foo', {
id = targetId
}, breeze.EntityState.Unchanged); // create as if freshly queried
foo.bar = 'new value'; // also sets 'originalValues' and changes the EntityState
manager.saveChanges(); // etc.
Let us know if that does the trick.
I can't find any info about this in the documentation, so I will ask here. How does breeze handle database column defaults? I have required columns in my database, but there are also default static values supplied for these in the database column definitions. Normally, I can insert null into these columns, and the new records will get the default. However, breeze doesn't seem to be aware of database column defaults, and the entities that have null in these columns fail validation on saving.
Thanks,
Mathias
Try editing the edmx xml by adding StoreGeneratedPattern = "Computed" attribute to the column with default value in the DB.
Edit:
Actually, before doing editing the xml, try setting the StoreGeneratedPattern property to Computed in the model editor itself.
Update:
This was fixed in Breeze 1.4.6 ( or later), available now.
Original Post:
There is currently in a bug in Breeze that should be fixed in the next release, out in about week. When this fix gets in then breeze will honor any defaultValues it finds in the EntityFramework data model.
One problem though is while it is easy to get 'defaultValues' into a Model First Entity Framework model via the properties editor, it's actually difficult to get it into a Code First EF model, unless you use fluent configuration. Unfortunately, EF ignores the [DefaultValue] attribute when constructing Code First model metadata.
One workaround that you can use now is to poke the 'defaultValue' directly onto any dataProperty. Something like:
var customerType = myEntityManager.metadataStore.getEntityType("Customer");
var fooProperty = customerType.getProperty("foo");
fooProperty.defaultValue = 123;
My existing table contains nearly 50 columns, most of them have the 'default' constraint.
I have created the model based on this database table. All seemed ok, until i tried to insert a new row. I've got a sql server error stating that some column cannot be null. It appears that creating a model from the database did not preserve the default constraints.
I edited the model manually adding all the defaults and after that inserting didn't fail.
So my question is, how do i create a model that automatically picks up default constraints associated to the columns?
Using mvc4, visual studio 2010, sql server 2008 r2.
Google search didnt make sense as all the people seemed to be talking about something different than what i need.
Pretty sure my answer from Possible to default DateTime field to GETDATE() with Entity Framework Migrations? will work for you too. By using a modified MigrationCodeGenerator class and iterating through the operations list you can update the columns and add DefaultValueSql values based on whatever rules you need.
Well, you have a number of options. You could set the default values in the Model's default constructor. I think this is the better solution.
If you must have the default constraints in your database you could do set defaultValueSql in your data migrations like this:
AddColumn("ExistingTable", "NewColumn",c => c.Int(nullable: false, defaultValueSql: "0"));
Using EF4 /w SQL Server 2008.
The following code (against a table with a PK, defined as Int IDENTITY(1,1):
ctx.AddObject(GetEntitySetName(), newEntity);
ctx.SaveChanges();
The results when profiling SQL are the insert statement following by a lookup against the table I'm inserting into:
SELECT ID FROM Table
WHERE ID = ##ScopeIdentity AND ##RowCount > 0
Is there a way to prevent EntityFramework from retreiving the Identity seed? I don't need the ID back in my .Net code and under high volume situations it seems like a wasted operation.
Altenatively, is there a way to tell EF to change the way it performs this operation? The strategy used goes against recommendations made by Microsoft in this defect report:
http://connect.microsoft.com/SQL/feedback/ViewFeedback.aspx?FeedbackID=328811
You cannot change this behavior when using database generated keys (properties marked with StorgeGeneratedPattern.Identity). EF needs a real key value for inserted entity so the only way to avoid the query is to not using database generated keys at all and handling it yourselves in the application.
Did you ever try to create a ASP.NET MVC Project with Firebird database...I try it, and is difficult..
My problem:
I have working Firebird provider for Visual Studio 2010.
I have correct database with all needed for increasing the id of the tables.
I have created ASP.NET MVC 3 project, with included database, like EDMX file, with entities.
When i try to insert a record into a table, there occurs a problem that says:
FirebirdSql.Data.Common.IscException: violation of PRIMARY or UNIQUE KEY constraint "PK_USERS" on table "USERS"
That means the id of the record that is created is not increased.
I have stored procedures that must generate new id.
My question is:
How to insert record in Firebird data table from ASP.NET?
In Firebird you need to use triggers in combination with sequences (generators) if you want to have auto-increment like behavior. Otherwise you need to make sure that you assign a unique id yourself.
To create the sequence:
CREATE SEQUENCE mytable_id_sq;
To create a trigger for assigning a unique i (on a table called mytable)
set term !! ;
CREATE TRIGGER T1_BI FOR mytable
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
if (NEW.ID is NULL) then NEW.ID = NEXT VALUE FOR mytable_id_sq;
END!!
set term ; !!
This trigger will only assign a generated value if no ID is assigned in the INSERT statement.
See also:
section SEQUENCE (GENERATOR) in the Firebird 2.5 Language Reference and How to create an autoincrement column? (this link talks about generators, the old name of sequences in Firebird).
Your EDMX isn't probably generated properly. Either you have to set the StoreGeneratedPattern manually or use http://blog.cincura.net/230841-generated-primary-key-in-entity-framework-model-from-firebird/ .