Foreign key allow null SQL - c#

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

Related

Sharing common database between .Net core and .Net standard Identity framework

I have old legacy MVC app that uses Identity 2.0. Also recently I have created .Net 6 API with Identity 6.0 (AspNetCore.Identity.EntityFrameworkCore).
Note: There are some schema related changes in both of this framework, like some additional tables and fields. check snapshot that I added at last.
The issue is the common database that I have to manage.
I have tried and successfully completed updation of existing database with latest schema.
I have also migrated the data for the identity tables.
The only issue I face right now is I'm not sure how to support old legacy app going further. (I want to have old app as it is, but want it to use new identity tables.)
Since the exisiting/old app is in .Net framework 4.6.1, I can not really update identity and it's tables to have latest schema in it. (I don't mind doing any hack or any fix. old app should work with latest idenitty schema is what imp for me at the moment.)
Is there any option that I can follow without changing code much, I have tight deadline to follow and I don't really want to create external API to authenticate old legacy app. Any help or idea would be really appreciated.
I didn't find any way to update existing app (.Net standard 4.6) to support new identity structure. So here is what I did to resolve this issue.
As #Jeremy suggested in comments, I configured my .Net core Identity models to have different names (other then by default, so it does not have any conflict with existing tables) https://learn.microsoft.com/en-us/aspnet/core/security/authentication/customize-identity-model?view=aspnetcore-6.0#change-tablecolumn-names-and-facets (keep order of model configuration as it is as given in thread. I got issues when I kept my base.OnModelCreating(builder); below builder configuration.)
I have found a script to create identity tables schema and move records. see below screenshot. _New represents the .Net core identity tables scehma. I have attached that script here with and I have run this script in common database.
So now I have common database with both old and new identity tables. old application is still pointing and working well with old tables which .Net core identity framework is poiting to new database.
Since I have moved all the data and records from old tables to new table, I can access them in new idenity app too.
Till now I have no need to run migration in new app, so I disabled it. but there was concern of what if I run migration and how will it affect existing database. so I did some R&D and found that we can create migration and before running that migration, we can just comment out the code inside the up and down method. after that we can run this migration and update database. basically empty migration to keep in sync with existing database. (haven't checked this working but this was my idea if I needed it)
Here is the sql Script that I used.
STEP 1 : Change name of existing tables
EXEC sp_rename 'AspNetRoles', 'AspNetRoles_old';
EXEC sp_rename 'AspNetUserClaims', 'AspNetUserClaims_old';
EXEC sp_rename 'AspNetUserLogins', 'AspNetUserLogins_old';
EXEC sp_rename 'AspNetUserRoles', 'AspNetUserRoles_old';
EXEC sp_rename 'AspNetUsers', 'AspNetUsers_old';
STEP 2 : Create ASP.NET Core Identity tables
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AspNetRoleClaims](
[Id] [int] IDENTITY(1,1) NOT NULL,
[RoleId] [nvarchar](450) NOT NULL,
[ClaimType] [nvarchar](max) NULL,
[ClaimValue] [nvarchar](max) NULL,
CONSTRAINT [PK_AspNetRoleClaims] 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
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AspNetRoles](
[Id] [nvarchar](450) NOT NULL,
[Name] [nvarchar](256) NULL,
[NormalizedName] [nvarchar](256) NULL,
[ConcurrencyStamp] [nvarchar](max) NULL,
CONSTRAINT [PK_AspNetRoles] 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
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AspNetUserClaims](
[Id] [int] IDENTITY(1,1) NOT NULL,
[UserId] [nvarchar](450) NOT NULL,
[ClaimType] [nvarchar](max) NULL,
[ClaimValue] [nvarchar](max) NULL,
CONSTRAINT [PK_AspNetUserClaims] 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
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AspNetUserLogins](
[LoginProvider] [nvarchar](128) NOT NULL,
[ProviderKey] [nvarchar](128) NOT NULL,
[ProviderDisplayName] [nvarchar](max) NULL,
[UserId] [nvarchar](450) NOT NULL,
CONSTRAINT [PK_AspNetUserLogins] PRIMARY KEY CLUSTERED
(
[LoginProvider] ASC,
[ProviderKey] 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
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AspNetUserRoles](
[UserId] [nvarchar](450) NOT NULL,
[RoleId] [nvarchar](450) NOT NULL,
CONSTRAINT [PK_AspNetUserRoles] PRIMARY KEY CLUSTERED
(
[UserId] ASC,
[RoleId] 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
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AspNetUsers](
[Id] [nvarchar](450) NOT NULL,
[UserName] [nvarchar](256) NULL,
[NormalizedUserName] [nvarchar](256) NULL,
[Email] [nvarchar](256) NULL,
[NormalizedEmail] [nvarchar](256) NULL,
[EmailConfirmed] [bit] NOT NULL,
[PasswordHash] [nvarchar](max) NULL,
[SecurityStamp] [nvarchar](max) NULL,
[ConcurrencyStamp] [nvarchar](max) NULL,
[PhoneNumber] [nvarchar](max) NULL,
[PhoneNumberConfirmed] [bit] NOT NULL,
[TwoFactorEnabled] [bit] NOT NULL,
[LockoutEnd] [datetimeoffset](7) NULL,
[LockoutEnabled] [bit] NOT NULL,
[AccessFailedCount] [int] NOT NULL,
CONSTRAINT [PK_AspNetUsers] 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
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AspNetUserTokens](
[UserId] [nvarchar](450) NOT NULL,
[LoginProvider] [nvarchar](128) NOT NULL,
[Name] [nvarchar](128) NOT NULL,
[Value] [nvarchar](max) NULL,
CONSTRAINT [PK_AspNetUserTokens] PRIMARY KEY CLUSTERED
(
[UserId] ASC,
[LoginProvider] ASC,
[Name] 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
SET ANSI_PADDING ON
GO
CREATE NONCLUSTERED INDEX [IX_AspNetRoleClaims_RoleId] ON [dbo].[AspNetRoleClaims]
(
[RoleId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
SET ANSI_PADDING ON
GO
CREATE UNIQUE NONCLUSTERED INDEX [RoleNameIndex] ON [dbo].[AspNetRoles]
(
[NormalizedName] ASC
)
WHERE ([NormalizedName] IS NOT NULL)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
SET ANSI_PADDING ON
GO
CREATE NONCLUSTERED INDEX [IX_AspNetUserClaims_UserId] ON [dbo].[AspNetUserClaims]
(
[UserId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
SET ANSI_PADDING ON
GO
CREATE NONCLUSTERED INDEX [IX_AspNetUserLogins_UserId] ON [dbo].[AspNetUserLogins]
(
[UserId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
SET ANSI_PADDING ON
GO
CREATE NONCLUSTERED INDEX [IX_AspNetUserRoles_RoleId] ON [dbo].[AspNetUserRoles]
(
[RoleId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
SET ANSI_PADDING ON
GO
CREATE NONCLUSTERED INDEX [EmailIndex] ON [dbo].[AspNetUsers]
(
[NormalizedEmail] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
SET ANSI_PADDING ON
GO
CREATE UNIQUE NONCLUSTERED INDEX [UserNameIndex] ON [dbo].[AspNetUsers]
(
[NormalizedUserName] ASC
)
WHERE ([NormalizedUserName] IS NOT NULL)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
ALTER TABLE [dbo].[AspNetRoleClaims] WITH CHECK ADD CONSTRAINT [FK_AspNetRoleClaims_AspNetRoles_RoleId] FOREIGN KEY([RoleId])
REFERENCES [dbo].[AspNetRoles] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[AspNetRoleClaims] CHECK CONSTRAINT [FK_AspNetRoleClaims_AspNetRoles_RoleId]
GO
ALTER TABLE [dbo].[AspNetUserClaims] WITH CHECK ADD CONSTRAINT [FK_AspNetUserClaims_AspNetUsers_UserId] FOREIGN KEY([UserId])
REFERENCES [dbo].[AspNetUsers] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[AspNetUserClaims] CHECK CONSTRAINT [FK_AspNetUserClaims_AspNetUsers_UserId]
GO
ALTER TABLE [dbo].[AspNetUserLogins] WITH CHECK ADD CONSTRAINT [FK_AspNetUserLogins_AspNetUsers_UserId] FOREIGN KEY([UserId])
REFERENCES [dbo].[AspNetUsers] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[AspNetUserLogins] CHECK CONSTRAINT [FK_AspNetUserLogins_AspNetUsers_UserId]
GO
ALTER TABLE [dbo].[AspNetUserRoles] WITH CHECK ADD CONSTRAINT [FK_AspNetUserRoles_AspNetRoles_RoleId] FOREIGN KEY([RoleId])
REFERENCES [dbo].[AspNetRoles] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[AspNetUserRoles] CHECK CONSTRAINT [FK_AspNetUserRoles_AspNetRoles_RoleId]
GO
ALTER TABLE [dbo].[AspNetUserRoles] WITH CHECK ADD CONSTRAINT [FK_AspNetUserRoles_AspNetUsers_UserId] FOREIGN KEY([UserId])
REFERENCES [dbo].[AspNetUsers] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[AspNetUserRoles] CHECK CONSTRAINT [FK_AspNetUserRoles_AspNetUsers_UserId]
GO
ALTER TABLE [dbo].[AspNetUserTokens] WITH CHECK ADD CONSTRAINT [FK_AspNetUserTokens_AspNetUsers_UserId] FOREIGN KEY([UserId])
REFERENCES [dbo].[AspNetUsers] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[AspNetUserTokens] CHECK CONSTRAINT [FK_AspNetUserTokens_AspNetUsers_UserId]
GO
STEP 3 : Migrate data from old tables (ASP.NET Identity) to new tables (ASP.NET Core Identity)
INSERT INTO AspNetRoles ([Id], [Name], [NormalizedName], [ConcurrencyStamp])
SELECT [Id], [Name], UPPER([Name]), LOWER(NEWID()) FROM Objectra_Development.dbo.AspNetRoles
INSERT INTO AspNetUsers ([Id], [UserName], [NormalizedUserName], [Email], [NormalizedEmail], [EmailConfirmed], [PasswordHash], [SecurityStamp], [ConcurrencyStamp], [PhoneNumber], [PhoneNumberConfirmed], [TwoFactorEnabled], [LockoutEnd], [LockoutEnabled], [AccessFailedCount],
AssignObjects, AccessOwnObjectsOnly, UserObjectId, UserObjectDefd, GoogleAuth, LastPasswordResetDate, FriendlyName, AccessibleObjectDefinitions)
SELECT [Id], [UserName], UPPER([UserName]), [Email], UPPER([Email]), [EmailConfirmed], [PasswordHash], [SecurityStamp], LOWER(NEWID()), [PhoneNumber], [PhoneNumberConfirmed], 0, null, 1, 0,
AssignObjects, AccessOwnObjectsOnly, UserObjectId, UserObjectDefd, GoogleAuth, LastPasswordResetDate, FriendlyName, AccessibleObjectDefinitions
FROM Objectra_Development.dbo.AspNetUsers;
INSERT INTO AspNetUserRoles ([UserId], [RoleId])
SELECT [UserId], [RoleId]
FROM Objectra_Development.dbo.AspNetUserRoles;
I faced the same problem and ended up creating new identity core tables using a schema.
builder.ToTable(name: "Users", "Identity");
builder.ToTable(name: "Roles", "Identity");
builder.ToTable(name: "UserRoles", "Identity");
builder.ToTable(name: "UserClaims", "Identity");
builder.ToTable(name: "UserLogins", "Identity");
builder.ToTable(name: "UserTokens", "Identity");
builder.ToTable(name: "RoleClaims", "Identity");
Then I used a trigger on the old identity users table to keep the new identity users table in sync.
CREATE/*ALTER*/ TRIGGER [dbo].[IdentityUsers_Sync] ON [dbo].[Users]
AFTER INSERT, UPDATE AS
BEGIN
--INSERT
IF NOT EXISTS (SELECT * FROM deleted)
BEGIN
INSERT INTO [Identity].[Users]
(
Id,
UserName,
NormalizedUserName,
Email,
NormalizedEmail,
EmailConfirmed,
PasswordHash,
SecurityStamp,
PhoneNumber,
PhoneNumberConfirmed,
TwoFactorEnabled,
LockoutEnabled,
AccessFailedCount
)
SELECT
Id,
UserName,
UPPER(UserName),
Email,
UPPER(Email),
EmailConfirmed,
PasswordHash,
SecurityStamp,
PhoneNumber,
PhoneNumberConfirmed,
TwoFactorEnabled,
0,
0
FROM inserted
END
--UPDATE
IF EXISTS (SELECT * FROM inserted) AND EXISTS (SELECT * FROM deleted)
BEGIN
UPDATE iu
SET
iu.UserName = i.UserName,
iu.NormalizedUserName = UPPER(i.UserName),
iu.Email = i.Email,
iu.NormalizedEmail = UPPER(i.Email),
iu.EmailConfirmed = i.EmailConfirmed,
iu.PasswordHash = i.PasswordHash,
iu.SecurityStamp = i.SecurityStamp,
iu.PhoneNumber = i.PhoneNumber,
iu.PhoneNumberConfirmed = i.PhoneNumberConfirmed,
iu.TwoFactorEnabled = i.TwoFactorEnabled,
iu.LockoutEnabled = 0,
iu.AccessFailedCount = 0
FROM [Identity].[Users] iu, inserted i
WHERE iu.Id = i.Id
END
END
GO
ALTER TABLE [dbo].[Users] ENABLE TRIGGER [IdentityUsers_Sync]
GO
And my plan is to create an api controller in the legacy system to handle new registrations (via HttpClient in any new Core apps). Then the trigger will pick it up and keep the new system in sync.
Having the legacy system use the new identity tables doesn't look like an option at this point. Maybe additional fields could be added to the new schema and use a trigger to fill them in? Haven't tried that.

The 'BldgTypeID' property on 'Building' could not be set to a 'System.Int16

I am getting this error below, I don't know what is the reason that I got this error. It works fine two days ago. I started to get this error yesterday.
Message = "The 'BldgTypeID' property on 'Building' could not be set to a 'System.Int16' value. You must set this property to a non-null value of type 'System.Int32'. "
Note
The DataType of BldgTypeID when I get the error is in smallint
Query
var data = db.Buildings.Select(t=>t).Tolist();
Database
CREATE TABLE [REC].[Building](
[BldgID] [bigint] IDENTITY(1,1) NOT NULL,
[ActionID] [int] NULL,
[TCTNo] [varchar](20) NULL,
[BldgTypeID] [smallint] NULL,
CONSTRAINT [PK_Building] PRIMARY KEY CLUSTERED
(
[BldgID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
I try to change the dataType from int into smallint vice versa. and still I got the same error. Even I update my EDMX.

How to assign id by customly?

i have an integer value id, it is okay and it is taking the value by default like 1,2, 3..... now i want to take this value like this 0001, 0002,0003. how can it possible please help me.
USE [Companybook]
GO
/****** Object: Table [dbo].[Employees] Script Date: 12/05/2013 14:50:14 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Employees](
[EmployeeID] [int] IDENTITY(1,1) NOT NULL,
[LastName] [nchar](10) NULL,
[FirstName] [nchar](10) NULL,
[Country] [nchar](10) NULL,
CONSTRAINT [PK_Employees] PRIMARY KEY CLUSTERED
(
[EmployeeID] 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
Hi you cant use 0001 as Identity in Sql, instead of that you can use valid number like 1001,2001,3001......
But you can retrieve the id as you said...
Please refer the link:
http://social.msdn.microsoft.com/Forums/en-US/9ae39780-9e95-4e91-bd9f-9f9fc9232084/how-to-make-int-identity-field-showed-like-0001-
http://forums.asp.net/t/1625788.aspx

Foreign Key in user defined table type

Hi I have a user defined tabletype
CREATE TYPE [dbo].[et] AS TABLE(
[id] [int] IDENTITY(1,1) NOT NULL,
[scId] [int] NOT NULL,
[eN] [int] NOT NULL,
[suppId] [int] NOT NULL,
)
GO
Than the target table I am trying to update/insert in to target table which is
CREATE TABLE [dbo].[test](
[id] [int] IDENTITY(1,1) NOT NULL,
[scId] [int] NOT NULL,
[eN] [int] NOT NULL,
[suppId] [int] NOT NULL,
CONSTRAINT [PK_test] 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].[t_test] WITH CHECK ADD CONSTRAINT [FK_test__supplyr] FOREIGN KEY([suppId])
REFERENCES [dbo].[supplyr] ([id])
GO
When I pass the table from my code using
SqlParameter param= cmdd.Parameters.Add(new SqlParameter("#mt", dt3));
I get error.
The MERGE statement conflicted with the FOREIGN KEY constraint........
Problem is Target table has the foreign key constrains while the user define table doesnt. How can I fix this problem? Thanks
Store procedure doing merge is
ALTER procedure [dbo].[testing2]
#mt[dbo].[et] readonly
as
Begin
merge into [dbo].[test] as Target
using #mt as Source
on Target.suppId =Source.suppId
when matched then
update set target.eN=Source.eN
when not matched then
insert (sCId,eN,suppId)
values (Source.sCId, Source.eN, Source.suppId);
End

Entity Framework 4 - How to Insert Records with Joiner Tables C#

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.

Categories

Resources