I have a table with 10 columns, in which 7 of them are not null with constraints on it.
ALTER TABLE [dbo].[MyTable]
ADD DEFAULT (1) FOR [Column1]
Now, when I am inserting 3 columns from Entity Framework like below, it is not inserting the default values into the table:
Table obj1 = new Table();
obj1.Column7 = someValue;
obj1.column8 = someValue;
obj1.column9 = someValue;
context.Entry(obj1).State = EntityState.Added;
context.SaveChanges();
Unlike my expectation, above statement is just updating 3 columns and not using the default values for the other 7 columns.
How can I enforce Entity Framework to insert default values defined by the constraint in database?
The default values as defined in your SQL Server table structure are only applied if you have an INSERT statement that leaves out those columns - e.g. doesn't provide any value (including NULL) for those columns.
EF however will always supply values for all columns as defined by the entity - e.g. it will supply NULL for any values not explicitly set. There's nothing you can do about this, as far as I know.
There are some workarounds:
you could create a stored procedure which would take only those values you want to supply, and would run a SQL INSERT statement that would leave out the columns with default values, e.g.
INSERT INTO dbo.MyTable (colA, colB, ..., colZ) -- *exclude* "Column1" here!
VALUES ( .........)
With this, SQL Server would then use the configured default values for those column that have one defined and which are not mentioned in the column list of the INSERT INTO statement
you could probably do something similar on the EF level, by specifying a second class, that would be almost identical to your current entity class - but that would leave out the columns you want to have set by SQL Server's configured default values. If you save this "slimmed down" entity, EF would create a SQL statement that would include only those columns that it knows about (in terms of the fields of that slimmed down class) and this would result basically in the same as above - an INSERT INTO statement that excludes those columns which are automatically set by a configured SQL Server default constraint
Related
I added a new column MyColumn to vwMyView in MyDB. MyDB has a stored procedure MySproc which returns vwMyView.* in a select statement.
When I execute MySproc, vwMyView.MyColumn is included in the result set. However, when I recreate my EF6 .edmx data model, MyColumn is not reflected in the EF vwMyView object or in MySproc_Result.
Is there a special trick I need to use so my new column MyColumn is reflected in a recreated EF6 .edmx? Is this a quirk that you encounter sometimes?
Happens sometimes, especially when the output is generated runtime as a polymorphic behavior (different result sets based on conditions)
In EF, for a result set, you may need to explictly create an output mapping. No need to delete the whole EDMX, just select the mapping (MySproc_Result) and update the result set to include the new column.
Are you creating the view inside procedure and then returning its value?
Inside the view, check if the columns are added conditionally (eg, if type=Sales, include 4 columns, if type=Mgmt, include 5 columns). The EF will pick up the 1st matching case in this condition.
Best way is to update the mapping and have the new column set as nullable, just in case some conditional makes it unavailable.
Entity Framework 6 with a Database Generated field is failing on insert. From what I've read once you mark a column as DatabaseGenerated, EF won't try to insert/update anything into that field, which is especially important in my case because the fields on the database are SQL Server computed columns and not just default values, which is what I've seen in a lot of similar questions on Stack Overflow/Google.
Column definition (using a User Defined Function in the computed column):
ALTER TABLE dbo.MyModel ADD [TotalUnits] AS ([dbo].[CalculateTotalUnits]([Id]));
EF definition:
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public decimal TotalUnits { get; private set; }
And then I'm just doing a
var myNewModel = new MyModel();
DbContext.MyModels.Add(myNewModel);
DbContext.SaveChanges();
Which gives:
System.Data.SqlClient.SqlException : Cannot insert the value NULL into column 'TotalUnits', table 'MyDatabase.dbo.MyModel'; column does not allow nulls. INSERT fails.
Why is EF trying to insert a NULL value into a computed column, and how can I tell it not to?
Turns out when running integration tests EF was configured to use Automatic Migrations instead of our own migrations. Since the computed columns were being added in a custom SQL script during the Up method of a migration, the columns weren't actually computed columns during the tests but were in fact generated by EF as regular decimal (non-nullable) fields. Thus trying to add a new model to the context was causing EF to insert NULL into those columns and blowing up.
Solution is to actually run the migrations in the integration tests. Once the column is actually computed than EF stops tracking it.
The issue is like , I got two tables X & Y. When records are added to table X , columns should be added to the table Y in parallel.
http://prntscr.com/3owqfe <-- Provides a clear Idea.
I tried it with triggers , but seems like the triggers doesnt allow CREATE TABLE or ALTER TABLE. Anyway as I'm using Linq , Im trying to achieve that via Linq. Any suggestions ?
Edited: For the record the below trigger worked , but with an exception.
create trigger AddItemToCommon ON [SEP].[dbo].[ItemMaster]
FOR INSERT
AS BEGIN
declare #PAYID varchar(max)
select #PAYID = payCode from INSERTED
ALTER TABLE [SEP].[dbo].[CommonPayrollItems]
ADD sampleCol varchar(max)
END
Anyway it will only run once because , there cannot be more than 1 column of the same name. But if I can retrieve the row values grom ItemMaster table , it's still possible with triggers. Which I tried to replace sampleCol with #PAYID which results in Syntax error.
Linq does not have functionality to create or alter tables. You could however use the underlying connection of your Linq Datacontext to execute any SQL statement:
DataContext.ExecuteCommand(...)
And use that to run your alter table statement. This will not update your Linq model of that table though.
If you plan to do this at runtime, you might want to reconsider your data model and create a third table (eg. STable2Extended) that contains a foreign key to both STable and STable2 combined with the applicable value for that column.
You could then add the STable2Extended to the datamodel and query it easily when you need the extended properties on STable2 without dynamically modifying tables.
Probably sounds like a silly question, but there is an aspect about it I would like to know:
I'm working with objects that have a Guid-property for PrimaryKeys, which gets auto-generated in the database. I am using Entity Framework, Code First. If I do a Console.WriteLine with this property before saving, the value is
00000000-0000-0000-0000-000000000000.
After using Add and SaveChanges in the context, if I do a Console.WriteLine again with the same property, I have a value:
615f98eb-4ced-422a-877f-b9caa6f2b91f
Obviously, the object in memory has been updates. But I want to know how. The Guid is genereated in the database, so what happens?
Does the Guid-property of the object simply get updated from the database through EF, or does EF reload the entire object into memory after saving it in the database?
I would like to know, because that will determine how I design NUnit-tests in the same project.
Your EF object is updated when you call domainContext.SaveChanges(); Your new Id is generated by SQL database and value of Id is return value from DB. It is same for data types int, Guid and similar.
EF does not only submit an Insert/Update statement, at the same time it does a get statement to retrieve the generated primary key. In fact it is one single query. Your entity's primary key is then updated with the retrieved one. No magic behind this.
That's also one of the reason why batch updates / inserts are not supported. Every entity has to be updated / inserted on its own.
This is a query that is being executed when inserting an entity with a computed int primary key:
insert [dbo].[TestTable]
([Name])
values ('myname' /* #0 */)
select [ID]
from [dbo].[TestTable]
where ##ROWCOUNT > 0
and [ID] = scope_identity()
As you can see, the insert statement is followed by a select statement retrieving the computed columns (in this case ID). If there are more computed columns they're all selected here.
I am using SQLServer 2008, WebForms, C#, Frameowrk 3.5, Entity Framework 1
I generated entity model from DB.
My DB has various tables & lets take example of one table user
It has fields id, name, email, created_on, is_active, is_on_leave
default values for is_active and on_leave properties are default to 0 ( zero ) in db
But When I try to insert a record in this table using entity model, it saves NULL in these fields. How to avoid this? I don't want to set a value for them from my page and want to use the one mentioned in DB.
How can I achieve that?
This columns can be nullable. Right click property in designer, choose properties and set StoreGeneratedPatern for property to computed in the property window.
I found similar question:
Set default value in EF designer datetime
The is_active and is_on_leave columns in your database are nullable. If you make them non-nullable the default values should be used when you do an insert.
ALTER TABLE [user] ALTER COLUMN [is_active] DEFAULT(0) NOT NULL
ALTER TABLE [user] ALTER COLUMN [is_on_leave] DEFAULT(0) NOT NULL
GO