I have an empty table that has two column : Id and Title .
The Id is guid type , Primary key , so Not Nullable .
I try to add a constraint for default value of Id , constraint is like this :
ALTER TABLE [dbo].[TestTable] ADD CONSTRAINT [DF_TestTable_Id] DEFAULT (newsequentialid()) FOR [Id]
GO
In Entity Framework , Because Id is not nullable , It fill the Id with '00000000-0000-0000-000000000000' value .
Therefor my constraint in sql doesn't work property for creating new sequentialId() and my first record in table get '00000000-0000-0000-000000000000' value.
And it's so obvious for the second row it get the:
"Vaiolation of PRIMARY KEY Constraint "PK_TestTable". Cannot insert Duplicate Key" error .
I know I could generate guid in .NeT like Guid.NewGuid() and fill the Id with value , But I'm trying to delegate this responsibility to sql and newsequentialId() default value .
I'm wonder how could I do that ?
For full info i put the entire script here :
CREATE TABLE [dbo].[TestTable](
[Id] [uniqueidentifier] NOT NULL,
[Title] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_TestTable] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[TestTable] ADD CONSTRAINT [DF_TestTable_Id] DEFAULT (newsequentialid()) FOR [Id]
GO
Update: My EF database first approach Mapping is:
public partial class TestTable
{
[DatabaseGenerated(DatabaseGenereatedOption.Computed)]
public System.Guid Id {get ;set;}
public string Title {get; set;}
}
Map your property Id as Computed like this:
Property(o => o.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
OR
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
OR, if you have edmx you must edit property in designer:
Unless you have some requirement to do this the hard way:
ALTER TABLE [dbo].[TestTable] ADD CONSTRAINT [DF_TestTable_Id]
DEFAULT (NEWID()) FOR [Id]
NEWID() is the TSQL equivalent of GUID.NewGuid()
Related
Slightly related to DataGridViewComboBoxCell Binding - "value is not valid" - I have an EF Database First project wherein I have three tables (and of course matching class representations):
AssayHistoricalValue
AssayResultType
AssayUsageType
The "Type" tables have Name descriptions in them, but the DataGridView needs to select Names from a ComboBox and store the ID itself in the DB behind the scenes.
I set all this up in the Edit Columns UI that makes adjustments to the Designer code - and everything looks proper:
Then, when I realized an error was being thrown:
DataGridViewComboBoxCell value is not valid
I realized a few others had this problem (such as the post I linked above) and online in other places. Some said suppressing the error as such worked for them, but this just results in an error along the lines of:
'Items collection cannot be modified when the DataSource property is
set.'
At the line where it does Items.Add below:
private void dataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e)
{
//Avoid error of data bound combobox cells
if (e.Exception.Message == "DataGridViewComboBoxCell value is not valid.")
{
object value = ConstantsGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
if (!((DataGridViewComboBoxColumn)ConstantsGridView.Columns[e.ColumnIndex]).Items.Contains(value))
{
((DataGridViewComboBoxColumn)ConstantsGridView.Columns[e.ColumnIndex]).Items.Add(value);
e.ThrowException = false;
}
}
}
Additionally, I tried just using the "AssayResultType" or Usage type object in the columns (which it prepops with when you add the the entity object/table you're trying to update) - and that doesn't work either.
I could probably more easily write LINQ statements and the like to populate all this as the structure is pretty simply, but I felt like the bindings set up here should do most the work for something like this. Thoughts on what might be up here?
SQL for 2 of tables in question (in case that's needed - if we can get 1 relationship working with Result Type the Usage Type should be fine too as it's the same really):
CREATE TABLE [dbo].[tblAssayHistoricalValue](
[AssayHistoricalValueId] [int] IDENTITY(1,1) NOT NULL,
[AssayResultTypeId] [int] NOT NULL,
[AssayUsageTypeId] [int] NOT NULL,
[MeanValue] [float] NOT NULL,
[StandardDeviationValue] [float] NOT NULL,
[RValue] [float] NOT NULL,
CONSTRAINT [PK_tblAssayHistoricalValue] PRIMARY KEY CLUSTERED
(
[AssayHistoricalValueId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[tblAssayHistoricalValue] WITH CHECK ADD CONSTRAINT [FK_tblAssayHistoricalValue_tblAssayResultType] FOREIGN KEY([AssayResultTypeId])
REFERENCES [dbo].[tblAssayResultType] ([AssayResultTypeId])
GO
ALTER TABLE [dbo].[tblAssayHistoricalValue] CHECK CONSTRAINT [FK_tblAssayHistoricalValue_tblAssayResultType]
GO
ALTER TABLE [dbo].[tblAssayHistoricalValue] WITH CHECK ADD CONSTRAINT [FK_tblAssayHistoricalValue_tblAssayUsageType] FOREIGN KEY([AssayUsageTypeId])
REFERENCES [dbo].[tblAssayUsageType] ([AssayUsageTypeId])
GO
ALTER TABLE [dbo].[tblAssayHistoricalValue] CHECK CONSTRAINT [FK_tblAssayHistoricalValue_tblAssayUsageType]
GO
CREATE TABLE [dbo].[tblAssayResultType](
[AssayResultTypeId] [int] NOT NULL,
[AssayId] [int] NOT NULL,
[Name] [varchar](50) NOT NULL,
[Description] [varchar](256) NULL,
CONSTRAINT [PK_tblAssayResultType] PRIMARY KEY CLUSTERED
(
[AssayResultTypeId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[tblAssayResultType] WITH CHECK ADD CONSTRAINT [FK_tblAssayResultType_tblAssay] FOREIGN KEY([AssayId])
REFERENCES [dbo].[tblAssay] ([AssayId])
GO
ALTER TABLE [dbo].[tblAssayResultType] CHECK CONSTRAINT [FK_tblAssayResultType_tblAssay]
GO
Based on the picture you allow user to add new records in the DataGridView. If this is a case, then DataGridView will try to bind default value for AssayResultTypeId column(integer => 0) to the DataSource of correspondent combobox column.
As workaround you can try disable Allow add rows option in your DataGridView.
Or add "empty" record to the binding source of the combobox column
var defaultResult = new AssayResultType { Id = 0, Name = "Please select type..." };
// Insert because you want keep it on the top of the list
resultTypesCollection.Insert(0, defaultResult);
I am a student and working on a college project.
I have created a simple scenario which I am facing in my project.
The simple database looks like this.
**Location Table**
CREATE TABLE [dbo].[Location] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[longitude] VARCHAR (50) NULL,
[latitude] VARCHAR (50) NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
);
**Role Table**
CREATE TABLE [dbo].[Role] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Name] VARCHAR (50) NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
);
**Another table**
CREATE TABLE [dbo].[Another] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Anything] VARCHAR (50) NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
);
**User Table**
CREATE TABLE [dbo].[User] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[name] VARCHAR (50) NULL,
[address] VARCHAR (50) NULL,
[loc_id] INT NOT NULL,
[role_id] INT NOT NULL,
[another_id] INT NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_User_lococation] FOREIGN KEY ([loc_id]) REFERENCES [dbo].[Location] ([Id]),
CONSTRAINT [FK_User_another] FOREIGN KEY ([another_id]) REFERENCES [dbo].[Another] ([Id]),
CONSTRAINT [FK_User_role] FOREIGN KEY ([role_id]) REFERENCES [dbo].[Role] ([Id])
);
I have populated Role table with following values
enter image description here
Now I want to add user using EntityFrameWorkCore
My controller looks like this
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Name,Address,RoleId")] User user)
{
if (ModelState.IsValid)
{
_context.Add(user);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
ViewData["LocId"] = new SelectList(_context.Location, "Id", "Id", user.LocId);
ViewData["RoleId"] = new SelectList(_context.Role, "Id", "Id", user.RoleId);
return View(user);
}
The problem is I want to Add User but it doesn't have a foreign key of Location table and Another table.
How can I create a Location_id and Another_id and put in User
I want my User object to get the foreign key of location table and another table.
Please help me, I don't know how to do that it will great help for me.Thanks
If you don't have info about FK, don't generate it randomly, make foreign key column nullable in class user. Surely, when you are using EF you have navigation properties in User class. You can add also int property which stores id of associated entity (this is advised, so if you don't have, create such property). Type of this property should (obviously) nullable, so use int?. Then update database, so FK column in DB will be also nullable. Then you will be able to insert user entity.
I have this table:
CREATE TABLE [dbo].[SandTable](
[Id] [uniqueidentifier] NOT NULL,
[Date] [date] NULL,
CONSTRAINT [PK_SandTable] PRIMARY KEY)
ALTER TABLE [dbo].[SandTable] ADD CONSTRAINT [DF_SandTable_Id] DEFAULT (NEWID()) FOR [Id]
Question is not about using NEWID() vs NEWSEQUENTIALID().
I use linqPad to test the table.
SandTables.InsertOnSubmit(new SandTable
{
// I don't provide any value for Id
Date = DateTime.Now
});
SubmitChanges();
My initial idea was to create an Id column that is able to initialize itself to a value when no Id is provided but will use the id provided when one is provided.
But because Guid is a struct, not a class the Id is never null, Id is initialized to his default value (00000000-0000-0000-0000-000000000000). So SQL server consider that Id has always a value and then the NEWID() default instruction is never called.
Is it possible to force the call to NEWID() on specific value? Should I use a trigger to evaluate the value of Id and when it's (00000000-0000-0000-0000-000000000000) then call NEWID()? What are the solutions or workaround?
You can do it with a check constraint:
ALTER TABLE [dbo].[SandTable]
ADD CONSTRAINT [DF_SandTable_Id] DEFAULT (NEWID()) FOR [Id]
ALTER TABLE [dbo].[SandTable]
WITH CHECK ADD CONSTRAINT [CK_SandTable_Id_Empty]
CHECK (
[Id] <> CAST(0x0 AS UNIQUEIDENTIFIER)
)
please check it this two tables.
create table Panda (id int identity, koalaId null)
create table Koala (id int identity)
I need that koalaId was foreign key to table Koala -> identity, but also I need that koalaId can be a NULL.
After this will be resolved, I need get data from Panda, but I get only a error:
Property koalaId for Panda not be set to null. This property must be set to a value that is not null and is of type Int32.
And I want for koalaId set to null.
Thank you for your advice.
By default a foreign key column will allow null value. you don't want to mention it explicitly.
**for example:**
Create table Kola(Id numeric identity(1,1) primary key)
Create table Panda(Id numeric identity(1,1),
KolaId numeric references Kola(Id))
*Note:*But make sure column 'id' in table 'kola' should be a primary key before it get referenced
by another table.
here is Panda and Cola creation codes:
CREATE TABLE [dbo].[Kola](
[id] [int] NOT NULL,
[kolaName] [nchar](10) NULL,
CONSTRAINT [PK_Kola] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Panda](
[id] [int] NOT NULL,
[KolaId] [int] NULL,
CONSTRAINT [PK_Panda] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Panda] WITH CHECK ADD CONSTRAINT [FK_Panda_Kola] FOREIGN KEY([KolaId])
REFERENCES [dbo].[Kola] ([id])
GO
ALTER TABLE [dbo].[Panda] CHECK CONSTRAINT [FK_Panda_Kola]
GO
I've been coding a very sizable project and I have run into trouble with EF4 and joiner table operations.
Suppose we have the following SQL table defintions:
CREATE TABLE [dbo].[SQLEntity](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[Field1] [nvarchar](128) NOT NULL,
[Field2] [nvarchar] (256),
[DateAdded] [datetime] NOT NULL,
CONSTRAINT [PK_SQLEntity] PRIMARY KEY CLUSTERED (
[Id] ASC
) WITH (
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON
) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE TABLE [dbo].[Util_LookupValues](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Description] [nvarchar](64) NOT NULL,
CONSTRAINT [PK_Util_LookupValues] PRIMARY KEY CLUSTERED (
[Id] ASC
)WITH (
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON
) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Xref_EntityValues](
[SQLEntityId] [bigint] NOT NULL,
[LookupId] [int] NOT NULL,
CONSTRAINT [PK_Xref_PositionBenefits] PRIMARY KEY CLUSTERED (
[SQLEntityId] ASC,
[LookupId] ASC
)WITH (
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON
) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Xref_EntityValues] WITH CHECK ADD CONSTRAINT [FK_Xref_EntityValues_Entity] FOREIGN KEY([SQLEntityId])
REFERENCES [dbo].[SQLEntity] ([Id])
GO
ALTER TABLE [dbo].[Xref_EntityValues] CHECK CONSTRAINT [FK_Xref_EntityValues_Entity]
GO
ALTER TABLE [dbo].[Xref_EntityValues] WITH CHECK ADD CONSTRAINT [FK_Xref_EntityValues_Util_LookupValues] FOREIGN KEY([LookupId])
REFERENCES [dbo].[Util_LookupValues] ([Id])
GO
ALTER TABLE [dbo].[Xref_EntityValues] CHECK CONSTRAINT [FK_Xref_EntityValues_Util_LookupValues]
GO
Once a domain model is crated based on these tables you'd end up with two Entities:
SqlEntity and Util_LookupValues.
At this point that the Util_LookupValues is a table whose values have been defined for lookups only! the Xref_EntityValues is a joiner table that would tie together the Entity object to the lookup value, allowing us to have a meny to meny relationship between the two, preserving the "lookup" functionality for the lookup table.
Util_LookupValues contents
Id Description
--- ------------
1 Person
2 Car
If no changes are added to the domain model (Lets for the purpose of this question call it DataEntities) then tying up a SQLEntity with Util_LookupValues objects whose PK is 1 and 2 would be done as follows:
IEnumerable<Util_LookupValues> lookupValues = DataEntities.Util_LookupValues.Where( lv => lv.Id == 1 || lv.Id == 2);
SQLEntity entity = new SQLEntity();
entity.Field1 = "some field";
entity.Field2 = "another field";
entity.DateAdded = DateTime.Now;
foreach(Util_LookupValues val in lookupValues)
{
entity.Util_LookupValues.Add(val);
}
DataEntities.SQLEntities.Add(entity);
DataEntities.SaveChanges();
Problem though is that instead of just adding values to the Xref_EntityValues, this code also adds a copy of 1 and 2 to the Util_LookupValues with new keys!
The resulting database is as follows:
SQL Entity:
Id Field1 Field2 DateAdded
-- ------- ------ ----------
1 some field another field 04/04/2012
Xref_EntityValues:
SQLEntityId LookupId
----------- ---------
1 3
1 4
and Util_LookupValues:
Id Description
--- ------------
1 Person
2 Car
3 Person
4 Car
How do I make it that Util_LookupValues only has the 2 original records and the Xref_EntityValues has the proper foreign keys?
Xref_EntityValues:
SQLEntityId LookupId
----------- ---------
1 1
1 2
Util_LookupValues:
Id Description
--- ------------
1 Person
2 Car
Does this line...
IEnumerable<Util_LookupValues> lookupValues = DataEntities.Util_LookupValues
.Where( lv => lv.Id == 1 || lv.Id == 2);
...and this line...
DataEntities.SQLEntities.Add(entity);
... use the same instance of the DataEntities context? Your code snippet indicates that but perhaps it's "pseudo code".
If the instances are different you get the duplication of entities, yes.
So, you have three options:
Make sure the context instances are the same.
Attach the returned Util_LookupValues to the second context:
foreach(Util_LookupValues val in lookupValues)
{
DataEntities.Util_LookupValues.Attach(val);
entity.Util_LookupValues.Add(val);
}
Don't perform the first query at all. Instead create "stub" entities and attach them:
var val = new Util_LookupValues { Id = 1 };
DataEntities.Util_LookupValues.Attach(val);
entity.Util_LookupValues.Add(val);
val = new Util_LookupValues { Id = 2 };
DataEntities.Util_LookupValues.Attach(val);
entity.Util_LookupValues.Add(val);
This work because EF only needs to know the primary key property value when you attach an object to the context to establish a new relationship.