Delete cascade on two 1:M foreign keys from same parent - c#

here are two tables in my Visual Studio 2015 project
Table 1:
CREATE TABLE [dbo].[Player] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[First_Name] NVARCHAR (50) NULL,
[Last_Name] NVARCHAR (50) NULL,
[Nickname] NVARCHAR (50) NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
);
and table 2:
CREATE TABLE [dbo].[Match] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Time] TIME (7) NULL,
[Winner_Id] INT NOT NULL,
[Loser_Id] INT NOT NULL,
[Tournament_Id] INT NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_Player_Winner] FOREIGN KEY ([Winner_Id]) REFERENCES [dbo].[Player] ([Id]),
CONSTRAINT [FK_Player_Loser] FOREIGN KEY ([Loser_Id]) REFERENCES [dbo].[Player] ([Id]),
CONSTRAINT [FK_Match_Tournament] FOREIGN KEY ([Tournament_Id]) REFERENCES [dbo].[Tournament] ([Id])
);
What I want is to add ON DELETE CASCADE on the foreign keys in the Match table, but I am unable to create a delete cascade on the player foreign keys. I would like to be able to do this, because if a player is deleted, I would like all matches he had participated in to be deleted as well, both as a winner and as a loser. My backup solution would be to add a column in Match that holds a "forfeit" value, so matches with this flag is not counted. This flag could be set when a player is deleted. Any idea how to implement this?

Related

Error when modifying a primary key as a foreign key

I have a primary key as a foreign key in Entity Framework.
public class RailcarTrip
{
[Key, ForeignKey("WaybillRailcar")]
public int WaybillRailcarId { get; set; }
public WaybillRailcar WaybillRailcar { get; set; }
// Etc.
}
This seems to work fine, and generates the following table.
CREATE TABLE [dbo].[RailcarTrips](
[WaybillRailcarId] [int] NOT NULL,
[StartDate] [datetime2](7) NOT NULL,
[DeliveryDate] [datetime2](7) NULL,
[ReleaseDate] [datetime2](7) NULL,
[ReturnDate] [datetime2](7) NULL,
[DeliveryEta] [datetime2](7) NULL,
[ReleaseEta] [datetime2](7) NULL,
[ReturnEta] [datetime2](7) NULL,
[ReturnCity] [nvarchar](80) NULL,
[ReturnState] [nvarchar](2) NULL,
[TripType] [int] NOT NULL,
CONSTRAINT [PK_RailcarTrips] PRIMARY KEY CLUSTERED
(
[WaybillRailcarId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[RailcarTrips] WITH CHECK ADD CONSTRAINT [FK_RailcarTrips_WaybillRailcars_WaybillRailcarId] FOREIGN KEY([WaybillRailcarId])
REFERENCES [dbo].[WaybillRailcars] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[RailcarTrips] CHECK CONSTRAINT [FK_RailcarTrips_WaybillRailcars_WaybillRailcarId]
GO
But I get an error when I try to change this PK/FK so that it references a different record.
The property 'RailcarTrip.WaybillRailcarId' is part of a key and so cannot be modified or marked as modified. To change the principal of an existing entity with an identifying foreign key, first delete the dependent and invoke 'SaveChanges', and then associate the dependent with the new principal.
I don't understand why this is a problem? The primary key is not set as an entity/autoset. This code should be a simple update of a FK. I don't want to have to delete anything. Can anyone explain why it's an issue?
This appears to be an Entity Framework error and not a SQL Server error.
EF doesn't support modifying primary keys. So you need to delete and insert (Remove+SaveChanges+Add+SaveChanges) the RailCarTrip to move it to a different WaybillRailcar. Alternatively you can update the PK/FK directly in TSQL.
If I understood You correctly, that is that you want to change the value of primary key of your entity (RailcarTrip), than You have answered Your own question - EF is informing you, that primary key is not a modifiable value, which is correct for SQL database.
It does not matter if this key is also a foreign key.
To modify a primary key value one has to delete corresponding entry and recreate it with new key value.

Migrate Users ASP.NET Web Pages tables to MVC 6

Info
I want to 'upgrade' my ASP.NET Web Page project to an ASP.NET MVC project by just starting over, it are only a few pages and it would be good for learning.
The Issue
The current project holds a few users for authentication
ASP.NET made a few tables in my database:
Roles
Profiles
Users
...
But when I use the MVC Project I see it makes different tables for authentication:
AspNetUserLogins
AspNetUserRoles
AspNetUser
...
The Question
How do I migrate my users or how do I tell ASP.net to use the old tables?
Greetings you may want to start with Database first Approach in MVC-Core but its little bit different from what you have seen so far, let me explain the steps for adding your database:
Install Entity Framework:
Run Install-Package Microsoft.EntityFrameworkCore.SqlServer
To enable reverse engineering from an existing database we need to install a couple of other packages too.
Run Install-Package Microsoft.EntityFrameworkCore.Tools –Pre
Run Install-Package Microsoft.EntityFrameworkCore.Design
Run Install-Package Microsoft.EntityFrameworkCore.SqlServer.Design
Now Reverse engineer your model:
Run the following command to create a model from the existing
database. If you receive an error stating the term
'Scaffold-DbContext' is not recognized as the name of a cmdlet, then
close and reopen Visual Studio.
Scaffold-DbContext "Server=(localdb)\mssqllocaldb;Database=DataBaseName;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models
The reverse engineer process created entity classes and a derived context based on the schema of the existing database. The entity classes are simple C# objects that represent the data you will be querying and saving. And now you can create a DbContext class and start using your database, so far you issue about database is over, and now i suggest you read about Identity In Asp.NET Core.
I came across this site thanks to this blog
And edited to fit my needs:
/****** Object: Table [dbo].[AspNetRoles] Script Date: 11/14/2013 1:56:03 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF OBJECT_ID('dbo.AspNetUserRoles', 'U') IS NOT NULL
DROP TABLE [dbo].[AspNetUserRoles]
GO
IF OBJECT_ID('dbo.AspNetUserLogins', 'U') IS NOT NULL
DROP TABLE [dbo].[AspNetUserLogins]
GO
IF OBJECT_ID('dbo.AspNetUserClaims', 'U') IS NOT NULL
DROP TABLE [dbo].[AspNetUserClaims]
GO
IF OBJECT_ID('dbo.AspNetRoles', 'U') IS NOT NULL
DROP TABLE [dbo].[AspNetRoles]
GO
IF OBJECT_ID('dbo.AspNetUsers', 'U') IS NOT NULL
DROP TABLE [dbo].[AspNetUsers]
GO
CREATE TABLE [dbo].[AspNetUsers] (
[AccessFailedCount] INT NOT NULL,
[Email] NVARCHAR (MAX) NULL,
[EmailConfirmed] BIT DEFAULT ((0)) NULL,
[Id] NVARCHAR (128) NOT NULL,
[LockoutEnabled] BIT DEFAULT ((0)) NULL,
[LockoutEndDateUtc] DATETIME2 (7) NULL,
[PasswordHash] NVARCHAR (MAX) NULL,
[PhoneNumber] NVARCHAR (MAX) NULL,
[PhoneNumberConfirmed] BIT DEFAULT ((0)) NULL,
[SecurityStamp] NVARCHAR (MAX) NULL,
[TwoFactorEnabled] BIT DEFAULT ((0)) NULL,
[UserName] NVARCHAR (MAX) NULL,
[CreateDate] DATETIME NULL,
[ConfirmationToken] NVARCHAR (128) NULL,
[IsConfirmed] BIT DEFAULT ((0)) NULL,
[LastPasswordFailureDate] DATETIME NULL,
[PasswordFailuresSinceLastSuccess] INT DEFAULT ((0)) NULL,
[PasswordChangedDate] DATETIME NULL,
[PasswordVerificationToken] NVARCHAR (128) NULL,
[PasswordVerificationTokenExpirationDate] DATETIME NULL,
CONSTRAINT [PK_dbo.AspNetUsers] PRIMARY KEY CLUSTERED ([Id] ASC)
);
GO
CREATE TABLE [dbo].[AspNetRoles] (
[Id] NVARCHAR (128) NOT NULL,
[Name] NVARCHAR (MAX) NOT NULL,
CONSTRAINT [PK_dbo.AspNetRoles] PRIMARY KEY CLUSTERED ([Id] ASC)
);
GO
CREATE TABLE [dbo].[AspNetUserRoles] (
[UserId] NVARCHAR (128) NOT NULL,
[RoleId] NVARCHAR (128) NOT NULL,
CONSTRAINT [PK_dbo.AspNetUserRoles] PRIMARY KEY CLUSTERED ([UserId] ASC, [RoleId] ASC),
CONSTRAINT [FK_dbo.AspNetUserRoles_dbo.AspNetRoles_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[AspNetRoles] ([Id]) ON DELETE CASCADE,
CONSTRAINT [FK_dbo.AspNetUserRoles_dbo.AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE
);
GO
CREATE NONCLUSTERED INDEX [IX_RoleId]
ON [dbo].[AspNetUserRoles]([RoleId] ASC);
GO
CREATE NONCLUSTERED INDEX [IX_UserId]
ON [dbo].[AspNetUserRoles]([UserId] ASC);
GO
CREATE TABLE [dbo].[AspNetUserLogins] (
[UserId] NVARCHAR (128) NOT NULL,
[LoginProvider] NVARCHAR (128) NOT NULL,
[ProviderKey] NVARCHAR (128) NOT NULL,
CONSTRAINT [PK_dbo.AspNetUserLogins] PRIMARY KEY CLUSTERED ([UserId] ASC, [LoginProvider] ASC, [ProviderKey] ASC),
CONSTRAINT [FK_dbo.AspNetUserLogins_dbo.AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE
);
GO
CREATE NONCLUSTERED INDEX [IX_UserId]
ON [dbo].[AspNetUserLogins]([UserId] ASC);
GO
CREATE TABLE [dbo].[AspNetUserClaims] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[ClaimType] NVARCHAR (MAX) NULL,
[ClaimValue] NVARCHAR (MAX) NULL,
[UserId] NVARCHAR (128) NOT NULL,
CONSTRAINT [PK_dbo.AspNetUserClaims] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_dbo.AspNetUserClaims_dbo.AspNetUsers_User_Id] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE
);
GO
CREATE NONCLUSTERED INDEX [IX_User_Id]
ON [dbo].[AspNetUserClaims]([UserId] ASC);
GO
INSERT INTO AspNetUsers(Id, UserName, PasswordHash, SecurityStamp,
CreateDate, ConfirmationToken, IsConfirmed, LastPasswordFailureDate, PasswordFailuresSinceLastSuccess,
PasswordChangedDate, PasswordVerificationToken, PasswordVerificationTokenExpirationDate,AccessFailedCount,LockoutEndDateUtc)
SELECT Users.UserId, Users.UserName, Memberships.Password,
Memberships.PasswordSalt, CreateDate,
null, 1, '1/1/1977', 0,
'1/1/2017', null, '1/1/2100',0,'1/1/1977'
FROM Users
LEFT OUTER JOIN Memberships ON Users.UserId = Memberships.UserId
GO
INSERT INTO AspNetRoles(Id, Name)
SELECT RoleId, RoleName
FROM Roles
GO
INSERT INTO AspNetUserRoles(UserId, RoleId)
SELECT UserId, RoleId
FROM UsersInRoles
GO
--INSERT INTO AspNetUserLogins(UserId, LoginProvider, ProviderKey)
--SELECT UserId, Provider, ProviderUserId
--FROM Memberships
--GO

Importing user-friendly Excel sheet into a SQL Server table that has many foreign keys

I have an Excel sheet that is populated by HR employee with thousands of client records it looks like this one:
User Friendly Excel Sheet Example Screenshot
My client's SQL Server table schema looks like this
CREATE TABLE [dbo].[Clients] (
[ID] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (100) NOT NULL,
[Photo] VARCHAR (200) NOT NULL,
[PolicyID] INT NOT NULL,
[BirthDay] DATE NOT NULL,
[Gender] BIT NOT NULL,
[Title] NVARCHAR (100) NULL,
[Nationality] NVARCHAR (100) NOT NULL,
[Relationship] NVARCHAR (50) NOT NULL,
[ClassID] INT NOT NULL,
[SponsorID] INT NULL,
[HRID] INT NOT NULL,
[Active] BIT CONSTRAINT [DF_Clients_Active] DEFAULT ((1)) NOT NULL,
[StartingDate] DATE NOT NULL,
[EndingDate] DATE NOT NULL,
[AddingDate] DATETIME NOT NULL,
[Creator] INT NOT NULL,
[UniqueID] NVARCHAR (50) NULL,
[PassportNo] NVARCHAR (50) NULL,
CONSTRAINT [PK_Clients] PRIMARY KEY CLUSTERED ([ID] ASC),
CONSTRAINT [FK_Clients_Clients] FOREIGN KEY ([SponsorID]) REFERENCES [dbo].[Clients] ([ID]),
CONSTRAINT [FK_Clients_Employees] FOREIGN KEY ([HRID]) REFERENCES [dbo].[Employees] ([ID]),
CONSTRAINT [FK_Clients_Employees1] FOREIGN KEY ([Creator]) REFERENCES [dbo].[Employees] ([ID]),
CONSTRAINT [FK_Clients_Policy] FOREIGN KEY ([PolicyID]) REFERENCES [dbo].[Policy] ([ID]),
CONSTRAINT [FK_Clients_Classes] FOREIGN KEY ([ClassID]) REFERENCES [dbo].[Classes] ([ID])
);
What is the best approach to achieve such inserts?
I've tried using SqlBulkCopy but it doesn't allow any manipulation on the inserted rows.
I've tried also using SqlAdapter.Update(Datatable) but it failed since I've read the Excel sheet using ExcelDataReader then tried to add some columns like Creator and Adding Date at runtime and when I tried to run Adapter.Update(ModifiedDatatable) it throws an exception
Update requires a valid UpdateCommand when passed DataRow collection with modified rows
When I tried to use SqlBulkCopy to insert this Excel sheet it worked as expected
Excel Sheet with Foreign Keys Screenshot
But it's not right to force the end user to put some foreign keys in the Excel sheet before import.
Notice:
Sorry for uploading screenshots to Tinypic but I couldn't upload them here because of my Rep Points.
Thanks in advance
I would be creating an SSIS package in this scenario. SSIS can read from Excel, and you can get it to query the database for the extra information to build a valid dataset that will not violate the FK constraints.

Entity Framework is not identifying primary key defined in database table

CREATE TABLE [Admin].[PlanManagers]
(
[ID] [bigint] IDENTITY(10000,1) CONSTRAINT PK_PLANMANAGERS Primary key NOT NULL,
[AdminUserId] [bigint]
CONSTRAINT FK_ADMINUSER_PLANMANAGERS
FOREIGN KEY REFERENCES [Login].[AdminUsers]([Id])
ON DELETE SET NULL NULL,
[PlanName] [nvarchar](255) NOT NULL,
[PlanIntro] [nvarchar](max) NULL,
[Active] [bit] Default(0) NOT NULL,
[Created] [datetime] Default(getutcdate()) NOT NULL,
[Updated] [datetime] Default(getutcdate()) NOT NULL,
[LastUpdatedBy] [BIGINT] NOT NULL,
)
I have added an Entity Framework Data Model for this database table but Entity Framework doesn't recognize the primary key.
I have manually mentioned the ID [Key] using data annotations.
What is the most possible cause of the bug..

Using table mapping in Entity Framework 6

I'm having lots of difficulty trying to use Entity Framework 6 for a simple application. I used the "EF Designer From Database" option, and something's wrong with my data model or my object model but I can't figure it out. I can't post images yet, but here is the SQL for my data model:
CREATE TABLE [dbo].[Customer](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Company] [varchar](100) NULL,
[Email] [varchar](50) NULL,
[FirstName] [varchar](50) NULL,
[LastName] [varchar](50) NULL,
[Phone] [varchar](20) NULL,
CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED ([ID] ASC)
)
GO
CREATE TABLE [dbo].[Feature](
[ID] [int] NOT NULL,
[Name] [varchar](100) NULL,
[Type] [char](1) NULL,
CONSTRAINT [PK_Feature] PRIMARY KEY CLUSTERED ([ID] ASC)
)
GO
CREATE TABLE [dbo].[License](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Comment] [varchar](max) NULL,
[CustomerID] [int] NULL,
[ExpirationDate] [datetime] NULL,
[SerialNumber] [char](26) NULL,
CONSTRAINT [PK_License] PRIMARY KEY CLUSTERED ([ID] ASC)
)
GO
CREATE TABLE [dbo].[LicenseItem](
[LicenseID] [int] NOT NULL,
[ItemID] [int] NOT NULL,
[Seats] [int] NULL,
CONSTRAINT [PK_LicenseItem] PRIMARY KEY CLUSTERED ([LicenseID] ASC, [ItemID] ASC)
)
GO
CREATE TABLE [dbo].[PackageModule](
[PackageID] [int] NOT NULL,
[ModuleID] [int] NOT NULL,
CONSTRAINT [PK_PackageModule] PRIMARY KEY CLUSTERED ([PackageID] ASC, [ModuleID] ASC)
)
GO
ALTER TABLE [dbo].[License] WITH CHECK ADD CONSTRAINT [FK_License_Customer] FOREIGN KEY([CustomerID])
REFERENCES [dbo].[Customer] ([ID])
GO
ALTER TABLE [dbo].[License] CHECK CONSTRAINT [FK_License_Customer]
GO
ALTER TABLE [dbo].[LicenseItem] WITH CHECK ADD CONSTRAINT [FK_LicenseItem_Feature] FOREIGN KEY([ItemID])
REFERENCES [dbo].[Feature] ([ID])
GO
ALTER TABLE [dbo].[LicenseItem] CHECK CONSTRAINT [FK_LicenseItem_Feature]
GO
ALTER TABLE [dbo].[LicenseItem] WITH CHECK ADD CONSTRAINT [FK_LicenseItem_License] FOREIGN KEY([LicenseID])
REFERENCES [dbo].[License] ([ID])
GO
ALTER TABLE [dbo].[LicenseItem] CHECK CONSTRAINT [FK_LicenseItem_License]
GO
ALTER TABLE [dbo].[PackageModule] WITH CHECK ADD CONSTRAINT [FK_PackageModule_ModuleID_Feature] FOREIGN KEY([ModuleID])
REFERENCES [dbo].[Feature] ([ID])
GO
ALTER TABLE [dbo].[PackageModule] CHECK CONSTRAINT [FK_PackageModule_ModuleID_Feature]
GO
ALTER TABLE [dbo].[PackageModule] WITH CHECK ADD CONSTRAINT [FK_PackageModule_PackageID_Feature] FOREIGN KEY([PackageID])
REFERENCES [dbo].[Feature] ([ID])
GO
ALTER TABLE [dbo].[PackageModule] CHECK CONSTRAINT [FK_PackageModule_PackageID_Feature]
GO
For my object model, I made Feature an abstract class and created Package and Module entities that inherit from Feature (feature is mapped to both Package and Module using Type as a discriminator). Package and Module are associated together with a many-to-many relationship, which is mapped to the PackageModule table, and I associated those to License so that License has Packages and Modules collections (with FK constraints). Here's where I'm stuck:
I added a Seats property to both Package and Module, deleted the auto-generated LicenseItem entity, and mapped LicenseItem to the Package and Module entities to map the Seats property to. This fails because the LicenseID PK is not mapped, and I just can't figure out how to get around this. I'm obviously missing something fundamental, so...be gentle. :)

Categories

Resources