EntityFramework populating uniqueidentifier with value "00000000-0000-0000-0000-000000000000" - entity-framework

In my WCF service I am using Entity Framework .NET 4.0,
in my database i have this table:
CREATE TABLE [dbo].[Tracking](
[TrackingID] [uniqueidentifier] ROWGUIDCOL NOT NULL,
...
CONSTRAINT [PK_Tracking] PRIMARY KEY CLUSTERED
(
[TrackingID] ASC
)
) ON [DATA]
ALTER TABLE [dbo].[Tracking] ADD CONSTRAINT [DF_Tracking_TrackingID] DEFAULT (newid()) FOR [TrackingID]
GO
when i insert a record Entity framewrok has prepopulated the TrackingID as "00000000-0000-0000-0000-000000000000". I have setting field property to be Computed and Identity bu no such luck any ideas: here is my code snippet:
using (var context = new DB.PTLEntities())
{
var tracking = new DB.Tracking();
context.Trackings.AddObject(tracking);
context.SaveChanges();
trackingID = tracking.TrackingID;
}

Looks like EF doesnt think this column is an identity column so its putting in default(Guid). Take a look here for some details on making a guid an identity column (it actually goes through your exact example) http://leedumond.com/blog/using-a-guid-as-an-entitykey-in-entity-framework-4/

I got same issue. Following solution worked for me.
There is a need to change the StoreGeneratedPattern value for the property in the EF designer. Set it to Identity. This will cause EF to avoid setting the value on an insert, then capture it after the insert is complete.
If your EF version is 4, then you may have trouble with this using the designer only. You may have to edit the .edmx manually and set the StoreGeneratedPattern in the storage model itself.
Example:
< Property Name="EmpId" Type="uniqueidentifier" Nullable="false" StoreGeneratedPattern="Identity" />

In my case (EF >= 4.1) I needed to add a default to the table itself:
ALTER TABLE MyTable ADD DEFAULT (newid()) FOR [Id]
Also if you're using your own context, you should tell EF that the column is the identity column:
public class ShedContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<DraftFromWebOneOff>()
.Property(d => d.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
base.OnModelCreating(modelBuilder);
}
}

Related

IDENTITY_INSERT ON error with foreign key

I'm trying to set Id manually for some entries.
I have a Customer class with an Identity field
modelBuilder.Entity<Customer>().Property(f => f.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity);
and in the insert part I have
using (var transaction = ctx.Database.BeginTransaction())
{
ctx.Database.ExecuteSqlCommand("SET IDENTITY_INSERT [dbo].[Customers] ON");
ctx.Customers.AddRange(customersList);
ctx.SaveChanges();
ctx.Database.ExecuteSqlCommand("SET IDENTITY_INSERT [dbo].[Customers] OFF");
transaction.Commit();
}
but I'm still getting the exception
Explicit value must be specified for identity column in table
'Customers' either when IDENTITY_INSERT is set to ON or when a
replication user is inserting into a NOT FOR REPLICATION identity
column.
In the StateEntries of my exception, I can see that all the fields that are stored in another table like "Contacts" seems to be the cause
customer.Contacts = new List<Contact> {new Contact {Name = "Test", … }}
How can I make it work?
That error message is misleading. You are succeeding in turning IDENTITY_INSERT on, but EF is still generating an INSERT statement under the assumption that the key value will be generated by the IDENTITY column.
So you additionally must generate an INSERT statement containing the key value. You can, of course, use .ExecuteSqlCommand() to perform the INSERT as well. Or you can get EF to do it, but you must use a model where that Entity does not have database-generated keys. OnModelCreating configures the model only once per ModelType, so you can't just put a switch in there.
Instead you can create a subtype of your DbContext for seeding, overriding the entity configuration of the base DbContext. Like this:
class Db_Seed: Db
{
public Db_Seed(string constr) : base(constr)
{
Database.SetInitializer<Db_Seed>(null); //no initializer
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Customer>().Property(c => c.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
}
}
You still must set IDENTITY_INSERT on (since the table does have an IDENTITY), but with this context EF will not generate an INSERT statement that assumes the server will generate the key.

Error Deleting Child Entity in Entity Framework 6

We are using EF6 database first with AspNet Identity. AspNetUsers is our table of customers. It extends AspNet IdentityUser. Each customer has many devices. The abbreviated table structures are
CREATE TABLE [dbo].[AspNetUsers] (
[Id] NVARCHAR (128) NOT NULL
);
CREATE TABLE [dbo].[Devices] (
[DeviceID] INT IDENTITY (1, 1) NOT NULL,
[UserId] NVARCHAR (128) NOT NULL
);
ALTER TABLE [dbo].[Devices]
ADD CONSTRAINT [FK_Devices_AspNetUsers] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]);
CustomersContext OnModelCreatingspecifies the relationship between AspNetUsers and Devices.
modelBuilder.Entity<ApplicationUser>()
.HasMany(e => e.Devices)
.WithRequired(e => e.User)
.HasForeignKey(e => e.UserId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Device>()
.HasKey(e => e.DeviceId);
modelBuilder.Entity<Device>().Property(e => e.UserId)
.IsRequired()
.HasMaxLength(450);
The following code
var userDevices = user.Devices.ToList();
foreach (Device device in userDevices)
{
user.Devices.Remove(device);
}
await customersContext.SaveChangesAsync();
fails with the error
Cannot insert the value NULL into column 'UserId', table 'Customers.dbo.Devices'
That appears to be trying to remove the relationship without deleting the device. How do I delete a device using EF?
You want to delete the device. It is not possible to just remove it from the Devices list, as it cannot exist stand-alone by itself. It has a non-nullable foreign key (from column UserId) referencing AspNetUsers(Id) - deletion would break referential integrity.
To delete the device, add following statement inside foreach loop to successfully delete the devices associated with a user.
customersContext.Entry(device).State = EntityState.Deleted;
Another way would be to place following code inside foreach loop to delete the device directly from the device repository itself, instead of going through Devices navigation property available on ApplicationUser entity:
customersContext.Devices.Remove(device);
If you don't want to delete the records from the Devices table and just want to remove the relationship between AspNetUsers and all the Devices in one go, then you can assign null to the navigation property and save the changes. This will remove the relation between the entities without physically deleting the records from database.
user.Devices = null;

How do I tell Entity (Code First) to not send the Key ID field to the database?

My code:
Models.Resource r = new Models.Resource();
r.Name = txtName.Text;
r.ResourceType = resTypes.Find(rt => rt.Name == "Content");
r.ResourceContents.Add(_resourceContent.Find(rc => rc.ID == _resourceContentID));
ctx.Resource.Add(r);
ctx.SaveChanges();
ctx.SaveChanges() causes the error:
Cannot insert explicit value for identity column in table 'Resources' when IDENTITY_INSERT is set to OFF.
Looking at what's being sent to SQL:
ADO.NET:Execute NonQuery "INSERT [dbo].[Resources]([ID], [Name], [Description], [IsOnFile],
[ContentOwnerAlias], [ContentOwnerGroup], [ResourceTypes_ID])
VALUES (#0, #1, #2, #3, #4, #5, NULL)"
My POCO Resource has ID as a Key:
public partial class Resource
{
public Resource()
{
}
[Key]
public int ID { get; set; }
And my Map code:
public class ResourceMap : EntityTypeConfiguration<Resource>
{
public ResourceMap()
{
// Primary Key
this.HasKey(t => t.ID);
How do I tell Entity to not send the Key ID field to the database?
If your PK is generated by the database (like an identity) you have to configure it in your Map.
public class ResourceMap : EntityTypeConfiguration<Resource>
{
public ResourceMap()
{
// Primary Key
this.HasKey(t => t.ID);
this.Property(t => t.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}
}
You do not need the HasKey(t => t.ID) Fluent API mapping or the [Key] Data Attribute because by convention EF will assume that an integer field named ID is the key and is database generated.
As an aside, I'd recommend that when you are not following conventions you should choose one method or the other - otherwise you are repeating yourself and when you want to change something you need to change it in 2 places.
I'm not sure why the field in the database isn't already database generated - maybe when you define the field via the fluent api you have to specify that too. What I do know is that in order to make EF change a key field to be database generated you will need to drop the table.
So - rollback the migration or drop the table / database, then remove the data attribute, remove the fluent mapping and recreate.
This issue is currently on a "backlog" in the entity framework. If you want to vote for it you can do that here: Migrations: does not detect changes to DatabaseGeneratedOption
Other References:
Identity problem in EF
Switching Identity On/Off With A Custom Migration Operation

EntityFramework - many-to-many reference in the DB without a backreference in the model

In my application users can define Parameters, and then create SlideSets based on a grouping of parameters.
I am using code-first Entity Framework 5.0 and I have the following model:
class SlideSet {
public ICollection<Parameter> Parameter
}
class Parameter {}
A parameter might be used by many slidesets or none at all. However, in my domain a parameter has no need to reference a SlideSet, they are in separate bounded contexts (both SlideSet and Parameter are Aggregate Roots). As such, I don't want to put a reference from Parameter to SlideSet.
The table model (I don't care about table/column names) that I want is
Table SlideSet
Table Param
Table SlideSetParam
FK_SlideSet
FK_Param
I know I could model this by introducing a ParameterGroup entity or a Param.SlideSets collection, but it would exist solely for ORM mapping purposes (and cause serialization issues). Is there any other way to tell EF to generate this table model from my entities?
This should make you a Parameter w/o a navigation property:
modelBuilder.Entity<SlideSet>()
.HasMany(x => x.Parameters)
.WithRequired();
EDIT:
Based on the comment - that should be all together similar. This seems to work nicely what you're trying to do....
modelBuilder.Entity<SlideSet>()
.HasMany(x => x.Parameters)
.WithMany();
...and you can use it either way:
var slideset = new SlideSet { Parameters = new []
{
new Parameter{},
new Parameter{},
new Parameter{},
new Parameter{},
}
};
var slideset2 = new SlideSet { };
db.SlideSets.Add(slideset);
db.SaveChanges();
var slidesets = db.SlideSets.ToList();
var parameters = db.Parameters.ToList();
Console.WriteLine("");
db.SlideSets.Add(slideset2);
db.SaveChanges();
slidesets = db.SlideSets.ToList();
parameters = db.Parameters.ToList();
Console.WriteLine("");
...and the SQL:
CREATE TABLE [dbo].[Parameters] (
[ParameterID] [int] NOT NULL IDENTITY,
CONSTRAINT [PK_dbo.Parameters] PRIMARY KEY ([ParameterID])
)
CREATE TABLE [dbo].[SlideSets] (
[SlideSetID] [int] NOT NULL IDENTITY,
CONSTRAINT [PK_dbo.SlideSets] PRIMARY KEY ([SlideSetID])
)
CREATE TABLE [dbo].[SlideSetParameters] (
[SlideSet_SlideSetID] [int] NOT NULL,
[Parameter_ParameterID] [int] NOT NULL,
CONSTRAINT [PK_dbo.SlideSetParameters] PRIMARY KEY ([SlideSet_SlideSetID], [Parameter_ParameterID])
)
CREATE INDEX [IX_SlideSet_SlideSetID] ON [dbo].[SlideSetParameters]([SlideSet_SlideSetID])
CREATE INDEX [IX_Parameter_ParameterID] ON [dbo].[SlideSetParameters]([Parameter_ParameterID])
ALTER TABLE [dbo].[SlideSetParameters] ADD CONSTRAINT [FK_dbo.SlideSetParameters_dbo.SlideSets_SlideSet_SlideSetID] FOREIGN KEY ([SlideSet_SlideSetID]) REFERENCES [dbo].[SlideSets] ([SlideSetID]) ON DELETE CASCADE
ALTER TABLE [dbo].[SlideSetParameters] ADD CONSTRAINT [FK_dbo.SlideSetParameters_dbo.Parameters_Parameter_ParameterID] FOREIGN KEY ([Parameter_ParameterID]) REFERENCES [dbo].[Parameters] ([ParameterID]) ON DELETE CASCADE
...this makes the original tables practically 'agnostic' of the relationships (many-to-many) - while index table is automatically generated in the background.
You can also further customize that and make your own SlideSetParam (e.g. if you'd want to add additional fields there) with pretty much the same layout - just Parameters would have to point to that instead.

I dont want to insert the PK val.But - Cannot insert explicit value for identity column in table 'Employees' when IDENTITY_INSERT is set to OFF

I am using the Entity Framework to update my database.
The Employee table has an employeeId primary key field.
When I instantiate an employee object, the employeeId defaults to zero.
I want to insert the employee object into the database, ignoring the primary key value of zero.
Yet I get this exception;
Cannot insert explicit value for identity column in table 'Employees' when IDENTITY_INSERT is set to OFF.
What should I be doing to stop this?
public void Add()
{
using (SHPContainerEntities db = new SHPContainerEntities())
{
// Set default values
this.StartDate = DateTime.Now;
// Start date now
this.SHP_UserRoleId = db.SHP_UserRoles.Where(x => x.RoleName == "Employee").Single().UserRoleId;
// Default user role is "Employee". This can be changed later.
this.DepartmentId = 1;
// This is a temporary fix.
db.AddToEmployees(this);
//db.Employees.AddObject(this);
db.SaveChanges();
}
}
I fixed the problem.
I updated the database and I forgot to update my edmx file to reflect that change.