EntityFramework mapping table wrong - c#

I have 2 tables:
Categories and
Users
The CategoryId is an int and the UserId is a string (nvarchar(128)).
I have this mapping for my user:
this.HasMany(t => t.ForbiddenCategories)
.WithMany(t => t.ForbiddenUsers)
.Map(m =>
{
m.ToTable("UserForbiddenCategories");
m.MapLeftKey("CategoryId");
m.MapRightKey("UserId");
});
but when I create a database for this, it does this:
CREATE TABLE [dbo].[UserForbiddenCategories](
[UserId] [int] NOT NULL,
[CategoryId] [nvarchar](128) NOT NULL,
CONSTRAINT [PK_dbo.UserForbiddenCategories] PRIMARY KEY CLUSTERED
(
[UserId] ASC,
[CategoryId] 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].[UserForbiddenCategories] WITH CHECK ADD CONSTRAINT [FK_dbo.UserForbiddenCategories_dbo.Categories_UserId] FOREIGN KEY([UserId])
REFERENCES [dbo].[Categories] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[UserForbiddenCategories] CHECK CONSTRAINT [FK_dbo.UserForbiddenCategories_dbo.Categories_UserId]
GO
ALTER TABLE [dbo].[UserForbiddenCategories] WITH CHECK ADD CONSTRAINT [FK_dbo.UserForbiddenCategories_dbo.IdentityUsers_CategoryId] FOREIGN KEY([CategoryId])
REFERENCES [dbo].[IdentityUsers] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[UserForbiddenCategories] CHECK CONSTRAINT [FK_dbo.UserForbiddenCategories_dbo.IdentityUsers_CategoryId]
GO
which is completely the wrong way around. CategoryId should be the int with a FK to Categories and UserId should be the string with a FK to IdentityUsers.
Can anyone tell me what I am doing wrong? Or how I can tell EF to change the maps around?
Cheers,
/r3plica

Related

How Can I Do Create Table by using sql query in NHibernate?

I have a dynamic table in my project, I doing mapping static table by using Nhibernate fluent API in the model solution. Dynamic table going to create at runtime. dynamic tables have dynamic columns. How can I do Create a dynamic table in NHibernate? thanks for help
CREATE TABLE [dbo].[Events](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](max) NULL,
[StartDate] [datetime] NOT NULL,
[EndDate] [datetime] NOT NULL,
[Quota] [int] NOT NULL,
[Description] [nvarchar](max) NULL,
CONSTRAINT [PK_dbo.Events] 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]
thanks for help.
I was already using Isession.CreateSqlQuery(sql) but not was working Create table
improved when replace code ' Isession.createSqlQuery(sql).executeUpdate()'

Prevent Insert Or Update data in C# or SQL

I have two table Header and Item, that has one to many Relation.
Header Table
Id StartDate EndDate
---------------------------------------
1 1999/1/1 1999/5/1
2 2000/1/1 2000/4/1
3 2000/1/1 2000/5/1
and Item Table
Id HeaderRef SLRef
-------------------------------------
101 1 201
102 2 201
How to Prevent to add Item with HeaderRef=3 and SLRef=201 because it has same SLRef, and the Header rows that HeaderRef referd to it has StartDate and EndDate that another Item with same SLRef Refered to Header in that Range.
Presuming you are using MS SQL Server there are two approaches to achive what you are looking for:
1) Use trigger as suggested by other users. Trigger would be for INSERT / UPDATE that will check the date ranges and will allow new values to be added or raise error.
2) You can use composite primary key in ItemTable:
CREATE TABLE [dbo].[ItemTable](
[Id] [int] IDENTITY(1,1) NOT NULL,
[HeaderRef] [int] NOT NULL,
[SLRef] [int] NOT NULL,
PRIMARY KEY CLUSTERED
(
[HeaderRef] ASC,
[SLRef] 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
Now this will put a constraint on the ItemTable and sql server WILL NOT allow duplicate combination of headerRef and SLRef int values (keys).
Back you your HeaderTable, you can put the unique constraint to stop duplicating the range of start and end dates
CREATE TABLE [dbo].[HeaderTable](
[ID] [int] IDENTITY(1,1) NOT NULL,
[STARTDATE] [datetime] not NULL,
[ENDDATE] [datetime] not NULL,
CONSTRAINT [PK_HeaderTable] 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
Now create unique index on HeaderTable for start and end dates.
/****** Object: Index [IX_HeaderTable] Script Date: 03/13/2017 12:24:51 ******/
CREATE UNIQUE NONCLUSTERED INDEX [IX_HeaderTable] ON [dbo].[HeaderTable]
(
[ENDDATE] ASC,
[STARTDATE] ASC
)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
You can also put another constraint on HeaderTable that will check if start date cant be before end date.
ALTER TABLE [dbo].[HeaderTable] WITH CHECK ADD CONSTRAINT [CheckEndLaterThanStart] CHECK (([ENDDATE]>=[STARTDATE]))
GO
ALTER TABLE [dbo].[HeaderTable] CHECK CONSTRAINT [CheckEndLaterThanStart]
GO
Hope this helps!
You Are Looking For a DML Trigger , in simple terms it's some sort of a sql function or procedure that is called automatically when the user try to change the data inside a database by adding or removing , Also the body of the trigger can contain some validation logic so it won't insert the data unless it meets a certain condition

The result of the expression is always true

I made a left join in linq and the value of UserId is NULLABLE (not in the table) but in the join and visual studio shows this warning.
I think this is a false positive because the code works well when userid is null IsSelected is false.
UserPrivilege class
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
public partial class UserPrivileges
{
public int Id { get; set; }
public int UserId { get; set; }
public int PrivilegeId { get; set; }
public virtual Privileges Privileges { get; set; }
public virtual UserProfile UserProfile { get; set; }
}
The linq query:
using (var dataContext = new MyEntities())
{
List<UserPrivilegesModel> result = (from privileges in dataContext.Privileges
join userPrivileges in dataContext.UserPrivileges on privileges.Id equals userPrivileges.PrivilegeId into tmpUserPrivileges
from userPrivileges in tmpUserPrivileges.DefaultIfEmpty()
//where userPrivileges.UserId == userId
select new UserPrivilegesModel { IsSelected = (userPrivileges.UserId != null), Description = privileges.Description, PrivilegeId = privileges.Id }).ToList();
return result;
}
On Linq userid == null is TRUE
SQL SCRIPT:
GO
/****** Object: Table [dbo].[Privileges] Script Date: 07/12/2016 10:35:21 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Privileges](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](20) NOT NULL,
[Description] [nvarchar](100) NOT NULL,
CONSTRAINT [PK_Privileges] 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
/****** Object: Table [dbo].[UserPrivileges] Script Date: 07/12/2016 10:35:21 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[UserPrivileges](
[Id] [int] IDENTITY(1,1) NOT NULL,
[UserId] [int] NOT NULL,
[PrivilegeId] [int] NOT NULL,
CONSTRAINT [PK_UserPrivileges_1] PRIMARY KEY CLUSTERED
(
[UserId] ASC,
[PrivilegeId] 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
/****** Object: Table [dbo].[UserProfile] Script Date: 07/12/2016 10:35:21 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[UserProfile](
[UserId] [int] IDENTITY(1,1) NOT NULL,
[UserName] [nvarchar](56) NOT NULL,
[Enabled] [smallint] NULL,
CONSTRAINT [PK__UserProf__1788CC4CB96C92F3] PRIMARY KEY CLUSTERED
(
[UserId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [UQ__UserProf__C9F28456208EB813] UNIQUE NONCLUSTERED
(
[UserName] 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].[UserPrivileges] WITH CHECK ADD CONSTRAINT [FK_UserPrivileges_Privileges] FOREIGN KEY([PrivilegeId])
REFERENCES [dbo].[Privileges] ([Id])
GO
ALTER TABLE [dbo].[UserPrivileges] CHECK CONSTRAINT [FK_UserPrivileges_Privileges]
GO
ALTER TABLE [dbo].[UserPrivileges] WITH CHECK ADD CONSTRAINT [FK_UserPrivileges_UserProfile] FOREIGN KEY([UserId])
REFERENCES [dbo].[UserProfile] ([UserId])
GO
ALTER TABLE [dbo].[UserPrivileges] CHECK CONSTRAINT [FK_UserPrivileges_UserProfile]
GO
SQL RELATIONSHIP
Should you be checking userPrivlages == null not userPrivlages.UserId == null? Also, should the 2nd from and the join be using the same name?
Try correcting those issues.
The type in the database may be nullable, but the type in the code is not. UserId is of type int, which can never be null. (Hence the error.) So presumably on a class somewhere you have something like this:
public int UserId { get; set; }
To make the type nullable, you would want this:
public int? UserId { get; set; }
Or, if you prefer, this:
public Nullable<int> UserId { get; set; }
This could have implications in other code not shown here about how to use that property, since you're changing the property's type. But this will allow that property to carry a null value.
userPrivaleges.UserId is not nullable, therefore (userPrivalegs.UserId != null) will always be true.

Custom database tables for Identity

I am trying to create custom tables for Identity Authentication, but I keep getting this error no matter how many times I have tried to recreate the Identity tables:
The entity types 'BBRoleType' and 'UserRoleType' cannot share table 'UserRoleTypes' because they are not in the same type hierarchy or do not have a valid one to one foreign key relationship with matching primary keys between them.
This is my User tables in the database:
And exported as SQL:
/****** Object: Table [dbo].[User] Script Date: 21/12/2015 18:42:21 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[User](
[Id] [uniqueidentifier] NOT NULL,
[Email] [nvarchar](255) NOT NULL,
[IsConfirmed] [bit] NOT NULL,
[PasswordHash] [nvarchar](500) NULL,
[SecurityStamp] [nvarchar](255) NULL,
[UserName] [nvarchar](255) NOT NULL,
[CreateDate] [datetime] NOT NULL,
[LastOnlineDate] [datetime] NOT NULL,
[BirthDate] [datetime] NULL,
[FacebookAccessToken] [nvarchar](max) NOT NULL,
[FacebookName] [nvarchar](500) NOT NULL,
[FacebookId] [nvarchar](max) NOT NULL,
CONSTRAINT [PK_User] 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
/****** Object: Table [dbo].[UserClaim] Script Date: 21/12/2015 18:42:22 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[UserClaim](
[Id] [bigint] NOT NULL,
[UserId] [uniqueidentifier] NOT NULL,
[ClaimValue] [nvarchar](max) NOT NULL,
[ClaimType] [nvarchar](max) NOT NULL,
CONSTRAINT [PK_UserClaim] 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
/****** Object: Table [dbo].[UserLogin] Script Date: 21/12/2015 18:42:22 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[UserLogin](
[UserId] [uniqueidentifier] NOT NULL,
[ProviderKey] [nvarchar](max) NOT NULL,
[LoginProvider] [nvarchar](max) NOT NULL,
[UserLoginId] [uniqueidentifier] NOT NULL,
CONSTRAINT [PK_UserLogin] PRIMARY KEY CLUSTERED
(
[UserLoginId] 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
/****** Object: Table [dbo].[UserRole] Script Date: 21/12/2015 18:42:22 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[UserRole](
[RoleId] [uniqueidentifier] NOT NULL,
[UserId] [uniqueidentifier] NOT NULL
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[UserRoleType] Script Date: 21/12/2015 18:42:22 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[UserRoleType](
[Id] [uniqueidentifier] NOT NULL,
[Name] [nvarchar](255) NOT NULL,
CONSTRAINT [PK_UserRoleType] 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].[User] ADD CONSTRAINT [DF_User_IsConfirmed] DEFAULT ((0)) FOR [IsConfirmed]
GO
ALTER TABLE [dbo].[UserLogin] ADD CONSTRAINT [DF_UserLogin_UserLoginId] DEFAULT (newid()) FOR [UserLoginId]
GO
ALTER TABLE [dbo].[UserRoleType] ADD CONSTRAINT [DF_UserRoleType_Id] DEFAULT (newid()) FOR [Id]
GO
ALTER TABLE [dbo].[UserClaim] WITH CHECK ADD CONSTRAINT [FK_UserClaim_User] FOREIGN KEY([UserId])
REFERENCES [dbo].[User] ([Id])
GO
ALTER TABLE [dbo].[UserClaim] CHECK CONSTRAINT [FK_UserClaim_User]
GO
ALTER TABLE [dbo].[UserLogin] WITH CHECK ADD CONSTRAINT [FK_UserLogin_User] FOREIGN KEY([UserId])
REFERENCES [dbo].[User] ([Id])
GO
ALTER TABLE [dbo].[UserLogin] CHECK CONSTRAINT [FK_UserLogin_User]
GO
ALTER TABLE [dbo].[UserRole] WITH CHECK ADD CONSTRAINT [FK_UserRole_User] FOREIGN KEY([UserId])
REFERENCES [dbo].[User] ([Id])
GO
ALTER TABLE [dbo].[UserRole] CHECK CONSTRAINT [FK_UserRole_User]
GO
ALTER TABLE [dbo].[UserRole] WITH CHECK ADD CONSTRAINT [FK_UserRole_UserRoleTyp] FOREIGN KEY([RoleId])
REFERENCES [dbo].[UserRoleType] ([Id])
GO
ALTER TABLE [dbo].[UserRole] CHECK CONSTRAINT [FK_UserRole_UserRoleTyp]
GO
After creating the table, I have added a ADO.NET Data Entity Model for the database.
I have created these classes to map to the custom Identity classes:
public class BBUserLogin : IdentityUserLogin<Guid> { }
public class BBUserRole : IdentityUserRole<Guid> { }
public class BBRoleType : IdentityRole<Guid,BBUserRole> { }
public class BBUserClaim : IdentityUserClaim<Guid> { }
public class BBUser : IdentityUser<Guid, BBUserLogin, BBUserRole, BBUserClaim>
{
public DateTime CreateDate { get; set; }
public DateTime LastOnlineDate { get; set; }
public DateTime? BirthDate { get; set; }
public string FacebookAccessToken { get; set; }
public string FacebookName { get; set; }
public string FacebookId { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<BBUser, Guid> manager)
{
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
userIdentity.AddClaim(new Claim(TCCustomClaimTypes.FirstName, this.FacebookName.SubstringUpToFirst(' ')));
return userIdentity;
}
}
And then setup my DbContext as this:
public class ApplicationDbContext : IdentityDbContext<BBUser, BBRoleType, Guid, BBUserLogin, BBUserRole, BBUserClaim>
{
public ApplicationDbContext() : base("MyIdentityConnection")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.HasDefaultSchema("dbo");
modelBuilder.Entity<BBUser>().ToTable("User");
modelBuilder.Entity<BBUserClaim>().ToTable("UserClaim");
modelBuilder.Entity<BBUserLogin>().ToTable("UserLogin");
modelBuilder.Entity<BBUserRole>().ToTable("UserRole");
modelBuilder.Entity<BBRoleType>().ToTable("UserRoleType");
modelBuilder.Entity<BBUser>().Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<BBUserClaim>().Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<BBRoleType>().Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}
Not that I think i matters, but I am using Guid/[uniqueidentifier] as Ids where I can (the places where the generic TKey is used). The IdentityUserClaim does not allow to change the Id-type, so I am using a bigint for that. Not that I think it matters :-)
I have been banging my head against the wall the entire day with this problem, but I can't figure out what I have done wrong.
It looks to me that the key names Id, Id, UserId, and RoleId need to have proper naming. Can you change the key 'Id' to 'UserId' on the 'User' table? Drop the Id key on UserClaim table. Change 'Id' on UserRoleType table to RoleId.
I think that will fix your issue.

Dataset and self referencing relationships Insert Exception

I am using c# datasets with a MSSQL back end. I have a table that references itself. When I add a parent row then add a child to that, without calling update in between I am getting a constraint exception. I think it is because the inserts are not being performed in the same order the entities were added. Is there any ways around this? I want the user to be able to add items and then commit to the database at the end (when they have confirmed it is all correct).
Here is my table definition and a sample application:
CREATE TABLE [dbo].[AssetServiceItems] (
[ServiceItemID] [int] IDENTITY(1, 1) NOT NULL,
[Description] [nvarchar](50) NOT NULL,
[Parent] [int] NULL,
CONSTRAINT [PK_AssetServiceItems] PRIMARY KEY CLUSTERED ([ServiceItemID] ASC) WITH (
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON
) ON [PRIMARY]
) ON [PRIMARY]
ALTER TABLE [dbo].[AssetServiceItems]
WITH CHECK ADD CONSTRAINT [AssetServiceItems_parent] FOREIGN KEY ([Parent]) REFERENCES [dbo].[AssetServiceItems]([ServiceItemID])
ALTER TABLE [dbo].[AssetServiceItems] CHECK CONSTRAINT [AssetServiceItems_parent]
and the program...
public static void Main(string[] args)
{
RelTestTableAdapters.AssetServiceItemsTableAdapter adapter = new RelTestTableAdapters.AssetServiceItemsTableAdapter();
RelTest dataSet = new RelTest();
var parent = dataSet.AssetServiceItems.NewAssetServiceItemsRow();
parent.Description = "Parent";
dataSet.AssetServiceItems.AddAssetServiceItemsRow(parent);
var child = dataSet.AssetServiceItems.NewAssetServiceItemsRow();
child.Description = "child";
child.SetParentRow(parent);
dataSet.AssetServiceItems.AddAssetServiceItemsRow(child);
adapter.Update(dataSet);
Console.ReadKey(true);
}
The INSERT statement conflicted with the FOREIGN KEY SAME TABLE
constraint "AssetServiceItems_parent". The conflict occurred in
database "RelTest", table "dbo.AssetServiceItems", column
'ServiceItemID'.

Categories