Dapper > I cannot retrieve object with child object - dapper

I have the following Quote and Share classes:
public class Quote
{
public Quote(string ticker, string name, decimal lastPrice)
{
this.Ticker = ticker;
this.Name = name;
this.LastPrice = lastPrice;
}
public string Ticker { get; private set; }
public string Name { get; private set; }
public decimal LastPrice { get; private set; }
}
public class Share
{
public Share(Quote quote, int quantity)
{
this.Quote = quote;
this.Quantity = quantity;
}
public Quote Quote { get; private set; }
public int Quantity { get; private set; }
}
And these tables:
CREATE TABLE [dbo].[quotes](
[ticker] [char](5) NOT NULL,
[name] [varchar](60) NOT NULL,
[last_price] [money] NOT NULL,
[bid_price] [money] NULL,
[bid_quantity] [int] NULL,
[ask_price] [money] NULL,
[ask_quantity] [int] NULL,
[high] [money] NULL,
[low] [money] NULL,
[previous_close] [money] NULL,
[created_by] [varchar](12) NULL,
[created_date] [datetime] NULL,
[modified_by] [varchar](12) NULL,
[modified_date] [datetime] NULL,
CONSTRAINT [PK_quotes] PRIMARY KEY CLUSTERED
(
[ticker] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[shares](
[ticker] [char](5) NOT NULL,
[broker_id] [char](12) NOT NULL,
[quantity] [int] NOT NULL,
[created_by] [varchar](12) NOT NULL,
[created_date] [datetime] NOT NULL,
[modified_by] [varchar](12) NULL,
[modified_date] [datetime] NULL,
CONSTRAINT [PK_shares] PRIMARY KEY CLUSTERED
(
[ticker] 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].[shares] WITH CHECK ADD CONSTRAINT [FK_shares_quotes] FOREIGN KEY([ticker])
REFERENCES [dbo].[quotes] ([ticker])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[shares] CHECK CONSTRAINT [FK_shares_quotes]
GO
And finally this code:
string sql = "SELECT quantity, s.ticker, name, last_price FROM shares s " +
"INNER JOIN quotes q ON q.ticker = s.ticker " +
"WHERE s.ticker=#ticker AND broker_id = #broker_Id";
IEnumerable<Share> shares = connection.Query<Share, Quote, Share>(sql,
(s, q) =>
{
Share share = new Share(q, s.Quantity);
return share;
},
new { ticker = ticker, broker_Id = brokerId }
, splitOn: "ticker");
return shares.FirstOrDefault();
When I execute that query, I get the following error:
"Specified method is not supported" (???)
If I modify the sql statement by the following (with "last_price as lastPrice"):
string sql = "SELECT quantity, s.ticker, name, last_price as lastPrice FROM shares s " +
"INNER JOIN quotes q ON q.ticker = s.ticker " +
"WHERE s.ticker=#ticker AND broker_id = #broker_Id";
I get the following error:
"A parameterless default constructor or one matching signature (System.String ticker, System.String name, System.Decimal lastPrice) is required for Footstock.Domain.Model.Quote materialization"
What am I doing wrong?

For the Share class, you need to either add a parameterless constructor or one that takes only a quantity parameter.
Before Dapper calls the method that composes the result to be returned, it needs to build the parameters to pass in to (s, q) => ... In your case you need a Share and a Quote class, both of which must have a constructor that can be called using the data Dapper has. For Quote, the constructor matches the properties in the query. For Share, Dapper only has the quantity and does not have a Quote object yet.

Related

Error converting data type varchar to int using stored procedure

I have two tables, one for primary key and second for foreign key. When I write the code to insert the data, I get an error.
ALTER PROCEDURE [dbo].[ImageHotSpotCRUD]
#ImaheHSMId int = NULL,
#ImaheHSName varchar(MAX) = '' ,
-- #patImage [varbinary](max)= NULL
#ImaheHSPath varchar(MAX) = '' ,
#ImaheHSDId int = NULL,
#ImaheHSDFKId int = NULL,
#ImaheHSXCordinate varchar(50) = '',
#ImaheHSYCordinate varchar(50) = '' ,
#ImaheHSDisc varchar(MAX) = '' ,
#IsActive varchar(1) = '' ,
#Created_by varchar(20) = '' ,
#CreatedDate datetime ='',
#ModifyDate datetime ='',
#ModifyBy varchar(50) = '',
#Mode varchar(1) =''
AS
BEGIN
SET NOCOUNT ON;
IF #Mode = '1'
BEGIN
-- Primary key table entry
DECLARE #ImageNEWPKId int = NULL
SELECT #ImageNEWPKId = HotSpotID
FROM M_ImageHotSpot
WHERE ImageName = #ImaheHSName
IF (#ImageNEWPKId IS NULL)
BEGIN
INSERT INTO M_ImageHotSpot (ImageName, ImagePath, Created_by, Created_date)
VALUES (#ImaheHSName, #ImaheHSPath, #Created_by, GETDATE())
SELECT #ImageNEWPKId = SCOPE_IDENTITY()
END
-- Foreign key table entry
DECLARE #ImageNEWDetailPKId int = NULL
SELECT #ImageNEWDetailPKId = HPDetailID
FROM M_ImageHotSpotDetail
WHERE HotSpotDescription = #ImaheHSDisc
IF (#ImageNEWDetailPKId IS NULL)
BEGIN
INSERT INTO M_ImageHotSpotDetail (HotspotIDFK, XCordinate, YCordinate, HotSpotDescription, CreatedByID, CreatedDate)
VALUES (#ImageNEWPKId, #ImaheHSXCordinate, #ImaheHSYCordinate, #ImaheHSDisc, #Created_by, GETDATE())
-- SELECT #ImaheHSMId = SCOPE_IDENTITY()
END
END
END
Here how I pass the data during button click in aspx.cs page:
exec ImageHotSpotCRUD
#Mode = '1', #ImaheHSName = 'x.jpeg', #ImaheHSPath = 'c:\',
#Created_by = 'ADMIN', #ImaheHSXCordinate = '100', #ImaheHSYCordinate = '100',
#ImaheHSDisc = 'You Selected Computer'
GO
I am using SQL Server Management Studio 18.
EDIT CODE 1
public int ImaheHSMId { get; set; }
public string ImaheHSName { get; set; }
public string ImaheHSPath { get; set; }
//Foreign Key Field
public int ImaheHSDId { get; set; }
//Foreign Key Id store here
public int ImaheHSDFKId { get; set; }
public string ImaheHSXCordinate { get; set; }
public string ImaheHSYCordinate { get; set; }
public string ImaheHSDisc { get; set; }
public string UserId { get; set; }
public bool IsDeleted { get; set; }
public bool IsActive { get; set; }
This are my class property and here is my Table Information. I did every thing perfect but still no data inserted.
Edit Code 2
Here is My both the table script.
CREATE TABLE [TRIEU].[M_ImageHotSpot](
[HotSpotID] [int] IDENTITY(1,1) NOT NULL,
[ImageName] [nvarchar](max) NULL,
[ImagePath] [nvarchar](max) NULL,
[IsActive] [bit] NULL,
[IsDeleted] [bit] NULL,
[Created_by] [nvarchar](18) NULL,
[Created_date] [datetime] NULL,
[Modified_by] [nvarchar](18) NULL,
[Modified_date] [datetime] NULL,
[stats_flag] [char](1) NULL,
CONSTRAINT [PK_M_ImageHotSpot] PRIMARY KEY CLUSTERED
(
[HotSpotID] 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 [TRIEU].[M_ImageHotSpotDetail](
[HPDetailID] [int] IDENTITY(1,1) NOT NULL,
[HotspotIDFK] [int] NULL,
[XCordinate] [nvarchar](50) NULL,
[YCordinate] [nvarchar](50) NULL,
[HotSpotDescription] [nvarchar](max) NULL,
[IsActive] [bit] NULL,
[IsDeleted] [bit] NULL,
[Created_by] [nvarchar](18) NULL,
[Created_date] [datetime] NULL,
[Modified_by] [nvarchar](18) NULL,
[Modified_date] [datetime] NULL,
[stats_flag] [char](1) NULL,
CONSTRAINT [PK_M_ImageHotSpotDetail] PRIMARY KEY CLUSTERED
(
[HPDetailID] 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
Dear JParmar,
INSERT INTO M_ImageHotSpotDetail (HotspotIDFK, XCordinate, YCordinate, HotSpotDescription, CreatedByID, CreatedDate)
VALUES (#ImageNEWPKId, #ImaheHSXCordinate, #ImaheHSYCordinate, #ImaheHSDisc, #Created_by, GETDATE())
For the above line, CreatedByID and CreatedDate column is not exist in M_ImageHotSpotDetail Table.

Identity Db : Duplicate email error even if constraint not set on the column

I am getting an exception of duplicate email in the identitydb while creating a user from my asp.net api.
The strange thing is that there is no constraint set on the email column or normalised email column so not
sure why it is not allowing me to enter same email address. Is there some default setting in the identity db for checking email dulication
Error
Code : "DuplicateEmail"
Description : "Email 'test#test.com' is already taken."
Execption caught while tracing in the profiler
exec sp_executesql N'EXEC GlobalExceptionInsert #DateTimeStamp, #Thread, #Class, #Method, #UserName, #Message, #Exception',N'#DateTimeStamp nvarchar(23),#Thread nvarchar(2),#Class nvarchar(13),#Method nvarchar(8),#UserName nvarchar(17),#Message nvarchar(115),#Exception nvarchar(163)',#DateTimeStamp=N'2019/10/23 14:26:13.078',#Thread=N'15',#Class=N'<AddUser>d__7',#Method=N'MoveNext',#UserName=N'Argentex.Core.Api',#Message=N'Error creating new user tmenon. Message: Code: DuplicateEmail. Description: Email ''test#test.com'' is already taken.',#Exception=N'Argentex.Core.Api.Exceptions.IdentityException: Error creating new user tmenon. Message: Code: DuplicateEmail. Description: Email ''test#test.com'' is already taken.'
Here is the screenshot of the table
Table
Constraint
Table definition
USE [IdentityDB_CSR]
GO
/****** Object: Table [dbo].[User] Script Date: 23/10/2019 13:28:45 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[User](
[Id] [bigint] IDENTITY(1,1) 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,
[AuthUserId] [int] NOT NULL,
[Title] [nvarchar](16) NOT NULL,
[Forename] [nvarchar](256) NOT NULL,
[Surname] [nvarchar](100) NOT NULL,
[ClientCompanyId] [int] NOT NULL,
[ClientCompanyContactId] [int] NOT NULL,
[UpdatedByAuthUserId] [int] NOT NULL,
[PhoneNumberMobile] [nvarchar](128) NULL,
[PhoneNumberOther] [nvarchar](128) NULL,
[LastUpdate] [datetime2](7) NULL,
[ASPNumber] [nvarchar](max) NULL,
[ASPCreationDate] [datetime2](7) NULL,
[LastTelephoneChange] [datetime2](7) NULL,
[LastEmailChange] [datetime2](7) NULL,
[LastPasswordChange] [datetime2](7) NOT NULL,
[CreateDate] [datetime2](7) NOT NULL,
[IsApproved] [bit] NOT NULL,
[Birthday] [datetime2](7) NULL,
[Notes] [nvarchar](max) NULL,
[Position] [nvarchar](50) NULL,
[PrimaryContact] [bit] NULL,
[IsDeleted] [bit] NOT NULL,
[IsAdmin] [bit] NOT NULL,
[ApprovedByAuthUserId] [int] NULL,
[IsAuthorisedSignatory] [bit] NOT NULL,
[IsSignatory] [bit] 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],
CONSTRAINT [AK_User_AuthUserId] UNIQUE NONCLUSTERED
(
[AuthUserId] 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
ALTER TABLE [dbo].[User] ADD DEFAULT (getdate()) FOR [LastPasswordChange]
GO
ALTER TABLE [dbo].[User] ADD DEFAULT (getdate()) FOR [CreateDate]
GO
ALTER TABLE [dbo].[User] ADD DEFAULT ((0)) FOR [IsAuthorisedSignatory]
GO
ALTER TABLE [dbo].[User] ADD DEFAULT ((0)) FOR [IsSignatory]
GO
Definition for UserNameIndex
USE [IdentityDB_CSR]
GO
SET ANSI_PADDING ON
GO
/****** Object: Index [UserNameIndex] Script Date: 23/10/2019 13:58:00 ******/
CREATE UNIQUE NONCLUSTERED INDEX [UserNameIndex] ON [dbo].[User]
(
[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
When creating user with ASP.NET Core Identity , it will raise the default UserValidator library which will make sure email is not empty, valid, and unique if options.User.RequireUniqueEmail of IdentityOptions is true :
if (manager.Options.User.RequireUniqueEmail)
{
await ValidateEmail(manager, user, errors);
}
ValidateEmail :
// make sure email is not empty, valid, and unique
private async Task ValidateEmail(UserManager<TUser> manager, TUser user, List<IdentityError> errors)
{
var email = await manager.GetEmailAsync(user);
if (string.IsNullOrWhiteSpace(email))
{
errors.Add(Describer.InvalidEmail(email));
return;
}
if (!new EmailAddressAttribute().IsValid(email))
{
errors.Add(Describer.InvalidEmail(email));
return;
}
var owner = await manager.FindByEmailAsync(email);
if (owner != null &&
!string.Equals(await manager.GetUserIdAsync(owner), await manager.GetUserIdAsync(user)))
{
errors.Add(Describer.DuplicateEmail(email));
}
}
Source code
You can set the options in ConfigureServices:
services.Configure<IdentityOptions>(options =>
{
options.User.RequireUniqueEmail = false;
...
});

#NamedQuery in Spring CrudRepository - SQLServerException: Invalid column name 'id'

I am calling a service that uses a #NamedQuery in a CrudRepository to return a domain object. I'm seeing the error
2017-04-05 16:43:16.063 WARN 14240 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 207, SQL
State: S0001
2017-04-05 16:43:16.065 ERROR 14240 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : Invalid column name
'id'.
2017-04-05 16:43:16.076 INFO 14240 --- [ main] utoConfigurationReportLoggingInitializer :
... 27 common frames omitted
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Invalid column name 'id'.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:232) ~[mssql-jd
bc-6.1.0.jre8.jar!/:na]
I don't understand this error as there is no column 'id' in my database table. Not sure what's going on
My table is
CREATE TABLE [dbo].[tb_changes_reports_v2](
[reportID] [int] NOT NULL,
[global_checksum] [int] NULL,
[specific_checksum] [int] NULL,
[batch] [int] NULL,
[pushed] [bit] NULL,
[compare_date] [datetime] NOT NULL,
[ver] [bigint] NULL
) ON [PRIMARY]
GO
My #Entity looks like
#Entity(name = "ChangesReports")
#Table(name="tb_changes_reports_v2")
#NamedQuery(name = "ChangesReports.findByTheReportId", query = "from ChangesReports c where c.reportId = ?1")
public class ChangesReports extends AbstractPersistable<Long> {
private static final long serialVersionUID = -452961221197917532L;
#Column(name="reportID", unique = true)
private Long reportId;
My #Repository looks like
#Repository
public interface ChangesReportsRepository extends CrudRepository<ChangesReports, Long>, ChangesReportsRepositoryCustom {
ChangesReports findByTheReportId(Long reportId);
My service looks like
#Override
public ChangesReports findByTheReportId(Long reportId) {
return changesReportsRepository.findByTheReportId(reportId);
}
I'm using these #Bean definitions to autowire my beans
#Bean
public ChangesReportsServiceImpl changesReportsServiceImpl() {
ChangesReportsServiceImpl changesReportsServiceImpl = new ChangesReportsServiceImpl();
return changesReportsServiceImpl;
}
#Bean
public ChangesReportsRepositoryImpl changesReportsRepository() {
ChangesReportsRepositoryImpl changesReportsRepositoryImpl = new ChangesReportsRepositoryImpl();
return changesReportsRepositoryImpl;
}
Again not sure why I'm receiving 'Invalid column name 'id'.' as there's no column named 'id'. Any ideas are appreciated.
Fyi the answer to me was to alter my table so that it has an ID column which was required by AbstractPersistable interface
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[tb_changes_reports_v2](
[ID] [int] IDENTITY(1,1) NOT NULL,
[reportID] [int] NOT NULL,
[global_checksum] [int] NULL,
[specific_checksum] [int] NULL,
[batch] [int] NULL,
[pushed] [bit] NULL,
[compare_date] [datetime] NOT NULL,
[ver] [bigint] NULL
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]

Entity Framework not calculating count() after grouping

The code will better explain what I'm trying to do.
var data = db.Absences//.AsExpandable()
.Where(a => a.Employee.EmployeeCode == "Emp1" || a.Employee.EmployeeCode == "Emp2" || a.Employee.EmployeeCode == "Emp3" || a.Employee.EmployeeCode == "Emp4" )
.Where(a=> a.Employee.Department.DepartmentCode == "HR" ||a.Employee.Department.DepartmentCode == "FIN" ||a.Employee.Department.DepartmentCode == "IT" )
.Where(a=> a.AbsenceId > 0)
.GroupBy(a => new
{
a.Employee.Department.DepartmentName,
a.Employee.Department.DepartmentCode,
a.Employee.IsPermanent
})
.Select(g => new ResultModel
{
Department = g.Key.DepartmentName,
Permanent = g.Key.IsPermanent,
TotalEmployeesInDepartment = g.Select(e => e.EmployeeCode).Distinct().Count(),
TotalAbsenceRecordsInCategory = g.Count(),
TotalLateCount = g.Select(x=> x.AbsenceCode == "Late").Count(),
TotalSickCount = g.Select(x=> x.AbsenceCode == "Sick").Count(),
TotalOnSiteCount = g.Select(x => x.AbsenceCode == "OnSite").Count(),
LatePercent = g.Select(x => x.AbsenceCode == "Late").Count() * 100.0 / g.Count(),
SickPercent = g.Select(x => x.AbsenceCode == "Sick").Count() * 100.0 / g.Count(),
OnSitePercent = g.Select(x => x.AbsenceCode == "OnSite").Count() * 100.0 / g.Count(),
});
I want total number of absences in a department, grouped by permanent vs non-permanent employees.
TotalAbsenceRecordsInCategory = g.Count() this is calculating fine in the generated SQL.
When I'm trying to get count of absences due to individual reasons the query is not working as expected.
TotalLateCount = g.Select(x=> x.AbsenceCode == "Late").Count(), this is not working, all of them are evaluated as
COUNT(1) AS [A1],
COUNT(1) AS [A2],
COUNT(1) AS [A3],
COUNT(1) AS [A4],.. so on
Below are my tables
CREATE TABLE [dbo].[Employees]
(
[DepartmentCode] [nvarchar](10) NOT NULL,
[EmployeeCode] [nvarchar](10) NOT NULL,
[EmployeeName] [nvarchar](20) NOT NULL,
[IsPermanent] [bit] NOT NULL,
CONSTRAINT [PK_Employees]
PRIMARY KEY CLUSTERED ([DepartmentCode] ASC, [EmployeeCode] 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].[Employees]
ADD CONSTRAINT [DF_Employees_IsPermanent] DEFAULT ((0)) FOR [IsPermanent]
GO
ALTER TABLE [dbo].[Employees] WITH CHECK
ADD CONSTRAINT [FK_Employees_Departments]
FOREIGN KEY([DepartmentCode]) REFERENCES [dbo].[Departments] ([DepartmentCode])
GO
ALTER TABLE [dbo].[Employees] CHECK CONSTRAINT [FK_Employees_Departments]
GO
CREATE TABLE [dbo].[Departments]
(
[DepartmentCode] [nvarchar](10) NOT NULL,
[DepartmentName] [nvarchar](20) NOT NULL,
CONSTRAINT [PK_Departments]
PRIMARY KEY CLUSTERED ([DepartmentCode] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[Absences]
(
[DepartmentCode] [nvarchar](10) NOT NULL,
[EmployeeCode] [nvarchar](10) NOT NULL,
[AbsenceId] [int] NOT NULL,
[AbsenceCode] [nvarchar](10) NOT NULL,
[AbsenceDate] [date] NOT NULL,
CONSTRAINT [PK_Absences_1]
PRIMARY KEY CLUSTERED ([DepartmentCode] ASC, [EmployeeCode] ASC, [AbsenceId] 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].[Absences] WITH CHECK
ADD CONSTRAINT [FK_Absences_Employees]
FOREIGN KEY([DepartmentCode], [EmployeeCode]) REFERENCES [dbo].[Employees] ([DepartmentCode], [EmployeeCode])
GO
ALTER TABLE [dbo].[Absences] CHECK CONSTRAINT [FK_Absences_Employees]
GO
One alternative is to say
TotalLateCount = g.Count(x=> x.AbsenceCode == "Late")
but this creates nested sub queries which I'm trying to avoid.
Any idea how can I get this to work? ResultModel is a simple class
public class ResultModel
{
public string Department { get; set; }
public bool Permanent { get; set; }
public int TotalAbsenceRecordsInCategory { get; set; }
public int TotalEmployeesInDepartment { get; set; }
public int TotalLateCount { get; set; }
public int TotalSickCount { get; set; }
public int TotalOnSiteCount { get; set; }
public double LatePercent { get; set; }
public double SickPercent { get; set; }
public double OnSitePercent { get; set; }
}

Error when inserting data in non-unique index

I have a batch job that synchronizes data between two identical databases using the MERGE statement. Sometimes, I get the following error: cannot insert duplicate key row in object 'dbo.MatchPlayerStatistics' with unique index 'IX_MatchPlayerStatistics_Player'. That does not make sense because IX_MatchPlayerStatistics_Player is not a unique index, and I am able to insert the exact same data manually. If I drop the index, insert the data, then recreate the index, it works fine.
Why does this error occur and how can I prevent it?
More information
The creation script for the table is the following:
CREATE TABLE [dbo].[MatchPlayerStatistics](
[ExternalID] [nvarchar](50) NULL,
[ProviderID] [int] NOT NULL,
[MatchID] [int] NOT NULL,
[PlayerPersonID] [int] NOT NULL,
[TeamID] [int] NOT NULL,
[YellowCards] [smallint] NULL,
[DoubleYellowCards] [smallint] NULL,
[RedCards] [smallint] NULL,
[Fouls] [smallint] NULL,
[Goals] [smallint] NULL,
[PenaltyGoals] [smallint] NULL,
[PenaltiesMissed] [smallint] NULL,
[PenaltiesSaved] [smallint] NULL,
[Shots] [smallint] NULL,
[Attacks] [smallint] NULL,
[Corners] [smallint] NULL,
[Offsides] [smallint] NULL,
[Assists] [smallint] NULL,
[OwnGoals] [smallint] NULL,
[GoalsConcedeed] [smallint] NULL,
[CreatedBy] [int] NOT NULL,
[CreatedOn] [datetime] NOT NULL,
[ModifiedBy] [int] NOT NULL,
[ModifiedOn] [datetime] NOT NULL,
CONSTRAINT [PK_MatchPlayerStatistics] PRIMARY KEY CLUSTERED
(
[ProviderID] ASC,
[MatchID] ASC,
[PlayerPersonID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE NONCLUSTERED INDEX [IX_MatchPlayerStatistics_Player] ON [dbo].[MatchPlayerStatistics]
(
[ProviderID] ASC,
[PlayerPersonID] 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]
The MERGE statement is the following:
MERGE MatchPlayerStatistics AS M
USING (
SELECT [ExternalID]
,[ProviderID]
,[MatchID]
,[PlayerPersonID]
,[TeamID]
,[YellowCards]
,[DoubleYellowCards]
,[RedCards]
,[Fouls]
,[Goals]
,[PenaltyGoals]
,[PenaltiesMissed]
,[PenaltiesSaved]
,[Shots]
,[Attacks]
,[Corners]
,[Offsides]
,[Assists]
,[OwnGoals]
,[GoalsConcedeed]
,[CreatedBy]
,[CreatedOn]
,[ModifiedBy]
,[ModifiedOn]
FROM [Replication].MatchPlayerStatistics
WHERE ProviderID = 1
) AS R
ON (M.MatchID = R.MatchID AND M.PlayerPersonID = R.PlayerPersonID AND M.ProviderID = R.ProviderID )
WHEN NOT MATCHED
THEN
INSERT ([ExternalID]
,[ProviderID]
,[MatchID]
,[PlayerPersonID]
,[TeamID]
,[YellowCards]
,[DoubleYellowCards]
,[RedCards]
,[Fouls]
,[Goals]
,[PenaltyGoals]
,[PenaltiesMissed]
,[PenaltiesSaved]
,[Shots]
,[Attacks]
,[Corners]
,[Offsides]
,[Assists]
,[OwnGoals]
,[GoalsConcedeed]
,[CreatedBy]
,[CreatedOn]
,[ModifiedBy]
,[ModifiedOn])
VALUES
( R.[ExternalID]
,R.[ProviderID]
,R.[MatchID]
,R.[PlayerPersonID]
,R.[TeamID]
,R.[YellowCards]
,R.[DoubleYellowCards]
,R.[RedCards]
,R.[Fouls]
,R.[Goals]
,R.[PenaltyGoals]
,R.[PenaltiesMissed]
,R.[PenaltiesSaved]
,R.[Shots]
,R.[Attacks]
,R.[Corners]
,R.[Offsides]
,R.[Assists]
,R.[OwnGoals]
,R.[GoalsConcedeed]
,R.[CreatedBy]
,R.[CreatedOn]
,R.[ModifiedBy]
,R.[ModifiedOn])
WHEN MATCHED
THEN
UPDATE
SET [ExternalID] = R.[ExternalID]
,[ProviderID] = R.[ProviderID]
,[MatchID] = R.[MatchID]
,[PlayerPersonID] = R.[PlayerPersonID]
,[TeamID] = R.[TeamID]
,[YellowCards] = R.[YellowCards]
,[DoubleYellowCards] = R.[DoubleYellowCards]
,[RedCards] = R.[RedCards]
,[Fouls] = R.[Fouls]
,[Goals] = R.[Goals]
,[PenaltyGoals] = R.[PenaltyGoals]
,[PenaltiesMissed] = R.[PenaltiesMissed]
,[PenaltiesSaved] = R.[PenaltiesSaved]
,[Shots] = R.[Shots]
,[Attacks] = R.[Attacks]
,[Corners] = R.[Corners]
,[Offsides] = R.[Offsides]
,[Assists] = R.[Assists]
,[OwnGoals] = R.[OwnGoals]
,[GoalsConcedeed] = R.[GoalsConcedeed]
,[CreatedBy] = R.[CreatedBy]
,[CreatedOn] = R.[CreatedOn]
,[ModifiedBy] = R.[ModifiedBy]
,[ModifiedOn] = R.[ModifiedOn]
WHEN NOT MATCHED BY SOURCE AND M.ProviderID = 1
THEN DELETE;
The [Replication].MatchPlayerStatistics table is an intermediate table that is filled with data from the [dbo].MatchPlayerStatistics table on another copy of the database. The schema for all these tables is the same.
One idea I have is to check and see if there are triggers on the table and if one of them is inserting to another table that has a unique index.
Looking at your code, here is a completely wild guess. You are using IGNORE_DUP_KEY = OFF which is normally only used for unique constraints, so I wonder if it is considering it a unique constraint even without the unique keyword. Try creating the index without that phrase and see what happens.

Resources