EF ##ROWCOUNT > 0 leads to wrong upsert - c#

I'm trying to update an existing in the DB entity (MamConfiguration_V1) call it Parent
I want to
1) add a reference (navigation) member to it (MamConfigurationToBrowser_V1) call it Child
2) I don't change the value of a unique property in the Parent entity. (Parent.Name)
I got the entity to update from the DB,
and using the same context (mMamDbEntities)
I add the reference member.
I don't change its Name property.
However I get a DB error, uniquness restriction violation
{"Violation of UNIQUE KEY constraint 'UQ_MamConfigurations_V1'. Cannot insert duplicate key in object 'dbo.MamConfiguration_V1'. The duplicate key value is (elad_14Apr_1315).\r\nThe statement has been terminated."}
I did DB sniffing and saw the generated code:
exec sp_executesql N'update [dbo].[MamConfiguration_V1]
set [Name] = #0, [Description] = #1, [StatusId] = #2, [Type] = #3, [UpdatedDate] = #4, [PercentageTraffic] = #5, [NumericTraffic] = #6
where ([ConfigurationId] = #7)
',N'#0 nvarchar(50),#1 nvarchar(200),#2 int,#3 int,#4 datetime2(7),#5 int,#6 int,#7 int',#0=N'elad_17Apr_1120_tmpToRemove_',#1=N'elad_22Apr_1120',#2=2,#3=0,#4='2013-04-23 11:17:25.4991650',#5=55,#6=-1,#7=32
//some more commands
exec sp_executesql N'insert [dbo].[MamConfiguration_V1]([Name], [Description], [StatusId], [Type], [CreatedDate], [UpdatedDate], [PercentageTraffic], [NumericTraffic])
values (#0, #1, #2, #3, #4, #5, #6, #7)
select [ConfigurationId]
from [dbo].[MamConfiguration_V1]
where ##ROWCOUNT > 0 and [ConfigurationId] = scope_identity()',N'#0 nvarchar(50),#1 nvarchar(200),#2 int,#3 int,#4 datetime2(7),#5 datetime2(7),#6 int,#7 int',#0=N'elad_17Apr_1120_tmpToRemove_',#1=N'elad_22Apr_1120',#2=2,#3=0,#4='0001-01-01 00:00:00',#5='0001-01-01 00:00:00',#6=55,#7=-1
I would have expected upsert to be ##ROWCOUNT = 0
What am I doing wrong?
My code and DB are:
public void SaveCofiguration(MamConfiguration_V1Ui itemUi)
{
var itemEf = mMamConfiguration_V1UiToEfConvertor.ConvertToNewEf(itemUi);
using (var maMDBEntities = new MaMDBEntities())
{
IDal<MamConfiguration_V1> mamConfigurationDal = mDalFactory.GetDal<MamConfiguration_V1>(maMDBEntities);
mamConfigurationDal.Save(itemEf);
}
}
public MamConfiguration_V1 GetById(object id)
{
id.ThrowIfNull("id");
int configurationId = Convert.ToInt32(id);
var result =
mMaMDBEntities.MamConfiguration_V1.SingleOrDefault(item => item.ConfigurationId == configurationId);
return result;
}
public MamConfiguration_V1 Save(MamConfiguration_V1 item)
{
item.ThrowIfNull("item");
var itemFromDB = GetById(item.ConfigurationId);
if (itemFromDB != null)
{
UpdateEfItem(itemFromDB, item);
// if (mMaMDBEntities.ObjectStateManager.GetObjectStateEntry(itemFromDB).State == EntityState.Detached)
// {
// mMaMDBEntities.MamConfiguration_V1.AddObject(itemFromDB);
// }
// Attached object tracks modifications automatically
mMaMDBEntities.SaveChanges();
return item;
}
private void UpdateEfItem(MamConfiguration_V1 itemFromDb, MamConfiguration_V1 itemFromUi)
{
itemFromDb.UpdatedDate = DateTime.Now;
itemFromDb.Description = itemFromUi.Description;
itemFromDb.StatusId = itemFromUi.StatusId;
itemFromDb.Name = itemFromUi.Name;
itemFromDb.NumericTraffic = itemFromUi.NumericTraffic;
itemFromDb.PercentageTraffic = itemFromUi.PercentageTraffic;
itemFromDb.Type = itemFromUi.NumericTraffic;
foreach (var item in itemFromDb.MamConfigurationToBrowser_V1.ToList())
{
if (itemFromUi.MamConfigurationToBrowser_V1.All(b => b.BrowserVersionId != item.BrowserVersionId))
{
mMaMDBEntities.MamConfigurationToBrowser_V1.DeleteObject(item);
}
}
for (int i = 0; i < itemFromUi.MamConfigurationToBrowser_V1.Count; i++)
{
var element = itemFromUi.MamConfigurationToBrowser_V1.ElementAt(i);
var item = itemFromDb.MamConfigurationToBrowser_V1.SingleOrDefault(b => b.BrowserVersionId == element.BrowserVersionId);
if (item != null)
{
// copy properties from element to item
}
else
{
element.Browser = mMaMDBEntities.Browsers.Single(browserItem =>
browserItem.BrowserID == element.BrowserID);
//element.MamConfiguration_V1 = itemFromDb;
//have also tried: element.MamConfiguration_V1 = null;
//element.MamConfiguration_V1Reference = null;
itemFromDb.MamConfigurationToBrowser_V1.Add(element);
}
}
}
Update:
mMaMDBEntities.SaveChanges(); throws the exception
These are the DB tables:
CREATE TABLE [dbo].[MamConfiguration_V1](
[ConfigurationId] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) NOT NULL,
[Description] [nvarchar](200) NOT NULL,
[StatusId] [int] NOT NULL,
[Type] [int] NOT NULL,
[CreatedDate] [datetime2](7) NOT NULL,
[UpdatedDate] [datetime2](7) NOT NULL,
[PercentageTraffic] [int] NOT NULL,
[NumericTraffic] [int] NOT NULL,
CONSTRAINT [PK_MamConfigurations_V1] PRIMARY KEY CLUSTERED
(
[ConfigurationId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [SECONDARY],
CONSTRAINT [UQ_MamConfigurations_V1] UNIQUE NONCLUSTERED
(
[Name] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [SECONDARY]
) ON [SECONDARY]
GO
ALTER TABLE [dbo].[MamConfiguration_V1] WITH CHECK ADD CONSTRAINT [FK_MamConfiguration_V1_ConfigurationType_V1] FOREIGN KEY([StatusId])
REFERENCES [dbo].[MamConfigurationStatuses] ([StatusId])
GO
ALTER TABLE [dbo].[MamConfiguration_V1] CHECK CONSTRAINT [FK_MamConfiguration_V1_ConfigurationType_V1]
GO
ALTER TABLE [dbo].[MamConfiguration_V1] ADD CONSTRAINT [DF_MamConfigurations_V1_CreatedDate] DEFAULT (getdate()) FOR [CreatedDate]
GO
ALTER TABLE [dbo].[MamConfiguration_V1] ADD CONSTRAINT [DF_MamConfigurations_V1_UpdatedDate] DEFAULT (getdate()) FOR [UpdatedDate]
GO
CREATE TABLE [dbo].[MamConfigurationToBrowser_V1](
[MamConfigurationId] [int] NOT NULL,
[BrowserVersionId] [uniqueidentifier] NOT NULL,
[IsWhiteListed] [bit] NOT NULL,
[BrowserID] [int] NOT NULL,
[VersionNumberLowRange] [varchar](50) NOT NULL,
[CreatedDate] [datetime] NOT NULL,
[UpdatedDate] [datetime] NOT NULL,
[VersionNumberUpperRange] [varchar](50) NULL,
CONSTRAINT [PK_MamConfigurationToBrowser_V1_1] PRIMARY KEY CLUSTERED
(
[BrowserVersionId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [SECONDARY]
) ON [SECONDARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[MamConfigurationToBrowser_V1] WITH CHECK ADD CONSTRAINT [FK_MamConfigurationToBrowser_V1_Browsers] FOREIGN KEY([BrowserID])
REFERENCES [dbo].[Browsers] ([BrowserID])
GO
ALTER TABLE [dbo].[MamConfigurationToBrowser_V1] CHECK CONSTRAINT [FK_MamConfigurationToBrowser_V1_Browsers]
GO
ALTER TABLE [dbo].[MamConfigurationToBrowser_V1] WITH CHECK ADD CONSTRAINT [FK_MamConfigurationToBrowser_V1_BrowserVersion] FOREIGN KEY([MamConfigurationId])
REFERENCES [dbo].[MamConfiguration_V1] ([ConfigurationId])
GO
ALTER TABLE [dbo].[MamConfigurationToBrowser_V1] CHECK CONSTRAINT [FK_MamConfigurationToBrowser_V1_BrowserVersion]
GO
ALTER TABLE [dbo].[MamConfigurationToBrowser_V1] ADD CONSTRAINT [DF_Browser_V1_CreatedDate] DEFAULT (getdate()) FOR [CreatedDate]
GO
ALTER TABLE [dbo].[MamConfigurationToBrowser_V1] ADD CONSTRAINT [DF_Browser_V1_UpdatedDate] DEFAULT (getdate()) FOR [UpdatedDate]
GO
Update 2
I have tried #AzharKhorasany solution, but go the same error:
for (int i = 0; i < itemFromUi.MamConfigurationToBrowser_V1.Count; i++)
{
var element = itemFromUi.MamConfigurationToBrowser_V1.ElementAt(i);
var item = itemFromDb.MamConfigurationToBrowser_V1.SingleOrDefault(b => b.BrowserVersionId == element.BrowserVersionId);
if (item != null)
{
// copy properties from element to item
}
else
{
element.Browser = mMaMDBEntities.Browsers.Single(browserItem =>
browserItem.BrowserID == element.BrowserID);
element.MamConfigurationId = itemFromDb.ConfigurationId;
//element.MamConfiguration_V1 = itemFromDb;
//have also tried: element.MamConfiguration_V1 = null;
//element.MamConfiguration_V1Reference = null;
//mMaMDBEntities.AddToMamConfigurationToBrowser_V1(itemFromUi.MamConfigurationToBrowser_V1.ElementAt(0)); // add as inserted
itemFromDb.MamConfigurationToBrowser_V1.Add(element);
}
}

Related

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.

How can I check if the DateTimes of an item is within the range of two other dates?

I am a new ASP.NET developer and I have 2 inputs in a form as DateTimes; StartDate and EndDate. I want to make sure that both of them are within the StartDate and EndDate of the Parent from another table. The logic should be as following:
Check if the StartDate of the items comes before the EndDate.
Check if the StartDate & EndDate of the inserted item is within the range of the StartDate and EndDate in the Customers table
So how can I do this logic?
For your information, I have two tables in the database, namely; Customers and Items.Their schema are:
Customers Table:
CREATE TABLE [dbo].[Customers](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NULL,
[Job] [varchar](50) NULL,
[StartDate] [datetime] NOT NULL,
[EndDate] [datetime] NOT NULL,
CONSTRAINT [PK_Customers] 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]
Items Table:
CREATE TABLE [dbo].[Items](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NOT NULL,
[Description] [varchar](50) NULL,
[StartDate] [datetime] NOT NULL,
[EndDate] [datetime] NOT NULL,
[CustomerID] [int] NOT NULL,
CONSTRAINT [PK_Items] 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
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[Items] WITH CHECK ADD CONSTRAINT [FK_Items_Customers] FOREIGN KEY([CustomerID])
REFERENCES [dbo].[Customers] ([ID])
GO
ALTER TABLE [dbo].[Items] CHECK CONSTRAINT [FK_Items_Customers]
GO
My C# Code:
protected void btnSubmit_Click(object sender, EventArgs e)
{
DateTime startDate = Convert.ToDateTime(txtStartDate.Text);
DateTime endDate = Convert.ToDateTime(txtEndDate.Text);
if (DateTime.Compare(startDate, endDate) <= 0)
{
using (TestDBEntities1 TEntities = new TestDBEntities1())
{
var newItem = new Item
{
Name = txtName.Text,
Description = txtDesc.Text,
StartDate = startDate,
EndDate = endDate,
CustomerID = Convert.ToInt32(ComboBox1.SelectedValue)
};
TEntities.Items.AddObject(newItem);
TEntities.SaveChanges();
}
lblMessage.Text = "Successfully Added :)";
}
else
{
lblMessage.Text = "Error!!!";
}
}
NOTE: I am using LINQ for querying the database. I am only missing the part of doing the logic for checking if the StartDate & EndDate of the inserted item is within the Dates in the Customers table.
Explanation:
For example, let us assume we have StartDate#1 and EndDate#1 for an item that will be inserted. In the Customers table, I have StartDate#2 and EndDate#2. The logic should do the following:
check if the StartDate#1 comes before EndDate#1
Then, check if StartDate#1 and EndDate#1 are falling within the range of StartDate#2 and EndDate#2

Weird behaviour in EF (possible bug)

I think I might have found a bug in Entity Framework.
I'm using Database First with MVC3.
I have the following table in my database:
CREATE TABLE [dbo].[InstructionStep](
[instructionID] [uniqueidentifier] NOT NULL,
[step] [numeric](18, 0) IDENTITY(1,1) NOT NULL,
[description] [nvarchar](max) NULL,
[recurrence] [numeric](18, 0) NULL,
[parameters] [nvarchar](50) NULL,
[secuence] [numeric](18, 0) NULL,
[time] [nvarchar](50) NULL,
CONSTRAINT [PK_InstructionStep] PRIMARY KEY CLUSTERED
(
[instructionID] ASC,
[step] 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'm using linq to EF to save/edit information into this table. The thing is... the "time" column, NEVER gets a value. I triple checked and the model DOES have a value for the time property of the object, but when I pass it to EF, it never makes it to the database. This is the code I use to create a new record:
using (Models.SAIMBehrEntities db = new Models.SAIMBehrEntities())
{
if (step.description != null)
step.description = step.description.ToUpper();
if (step.parameters != null)
step.parameters = step.parameters.ToLower();
db.InstructionSteps.AddObject(step);
db.SaveChanges();
}
this is the code I use to edit a record:
Models.InstructionStep s = db.InstructionSteps.Where(x => x.instructionID == stepM.instructionID && x.step == stepM.step).FirstOrDefault();
if (s != null)
{
s.parameters = stepM.parameters;
s.description = stepM.description;
s.recurrence = stepM.recurrence;
s.secuence = stepM.secuence;
s.time = stepM.time;
db.SaveChanges();
}
Everything else gets saved, except the "time" column. Now, I fired up sql profiler. This is the query generated by the create method:
exec sp_executesql N'insert [dbo].[InstructionStep]([instructionID], [description], [recurrence], [parameters], [secuence])
values (#0, #1, #2, #3, #4)
select [step], [time]
from [dbo].[InstructionStep]
where ##ROWCOUNT > 0 and [instructionID] = #0 and [step] = scope_identity()',N'#0 uniqueidentifier,#1 nvarchar(max) ,#2 decimal(18,0),#3 nvarchar(50),#4 decimal(18,0)',#0='9013B4B0-28FB-4C52-912D-3598A8E13880',#1=N'DEMO DESCRIPTION',#2=1,#3=N'none',#4=1
And this is the query generated by the update method:
exec sp_executesql N'update [dbo].[InstructionStep]
set [description] = #0, [recurrence] = #1, [parameters] = #2, [secuence] = #3
where (([instructionID] = #4) and ([step] = #5))
select [time]
from [dbo].[InstructionStep]
where ##ROWCOUNT > 0 and [instructionID] = #4 and [step] = #5',N'#0 nvarchar(max) ,#1 decimal(18,0),#2 nvarchar(50),#3 decimal(18,2),#4 uniqueidentifier,#5 decimal(18,0)',#0=N'DEMO DESCRIPTION',#1=1,#2=N'none',#3=1.00,#4='9013B4B0-28FB-4C52-912D-3598A8E13880',#5=1386
So... yeah. The "time" column gets selected after an update/insert. Why? beats me...
I tried changing the column name to "timestep" and worked correctly.
Is this a normal behaviour? am I just being plain stupid or is this a bug?
Thanks!

Linq To Sql duplicate a row in update case

I have a single entity that always duplicate a row when it needs to update:
protected static Task RegisterToDisc(Task task)
{
try
{
using (DataContext context = new DataContext())
{
//this will print an actual existing id from the db
_log.Debug(task.ID);
context.Tasks.InsertOnSubmit(task);
context.SubmitChanges();
}
}
catch(Exception e)
{
//...
}
return task;
}
When I print the id before the save, it is actually prints out an id that is really exists in the db.
this is the table:
CREATE TABLE [dbo].[TaskSet](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Message] [nvarchar](max) NOT NULL,
[Result] [nvarchar](max) NOT NULL,
[Status] [int] NOT NULL,
[Priority] [int] NOT NULL,
[Name] [nvarchar](max) NOT NULL,
[DateTimeAsked] [datetime] NOT NULL,
[DateTimePerfomed] [datetime] NOT NULL,
[SessionID] [nvarchar](max) NOT NULL,
CONSTRAINT [PK_TaskSet] 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
Edit
The task is comming from the database already, task.ID contains a number that is exists in the database, how come Linq inserts an entity with PK that is not null and in the db already.
in java hibernate you neet to context.insertOrUpdate(task); and it will decide what to do by the primary key.
InsertOnSubmit always marks the object for insertion. if you want to update the object u need to read it from database like
var objToUpdate = context.Tasks.SingleOrDefault(x=>x.Id == Id);
objToUpdate.Property1 = "updated value";
objToUpdate.Property2 = "updated value";
//do it for all properties that need updating
context.SubmitChanges();//since the object is tracked by context it will automatically generate sql to reflect update in db

Categories