SQL Server 2016 unique identifier and foreign keys - sql-server-2016

I have a simple db table that stores actions taken by the user.
CREATE TABLE [admin].[AuditRecords]
(
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[TypeName] [varchar](200) NOT NULL,
[IssuedBy] [uniqueidentifier] NOT NULL,
[IssuedOn] [datetimeoffset](0) NOT NULL,
[Details] [varchar](max) NOT NULL,
CONSTRAINT [PK_AuditRecords]
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
ALTER TABLE [admin].[AuditRecords] WITH CHECK
ADD CONSTRAINT [FK_AuditRecords_UserDetails]
FOREIGN KEY([IssuedBy])
REFERENCES [security].[UserDetails] ([Id])
GO
There's a FK from from auditrecord table to the user details table.
CREATE TABLE [security].[UserDetails]
(
[Id] [uniqueidentifier] NOT NULL,
[Email] [varchar](256) NOT NULL,
[FirstName] [varchar](256) NOT NULL,
[LastName] [varchar](256) NOT NULL,
[UserStatusId] [int] NOT NULL,
[PhoneNumber] [varchar](20) NOT NULL,
[FaxNumber] [varchar](20) NOT NULL,
[SignatureId] [int] NULL,
[SignatureFilePath] [varchar](256) NOT NULL,
[CreatedDate] [datetime] NOT NULL,
[ModifiedDate] [datetime] NOT NULL,
CONSTRAINT [PK__UserDeta__3214EC070E7DD00C]
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 [UQ_UserDetails_Email]
UNIQUE NONCLUSTERED ([Email] 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
I have the following SQL statement that I am using to update the database
INSERT INTO admin.AuditRecords (TypeName, IssuedBy, IssuedOn, Details)
VALUES (#TypeName, #IssuedBy, #IssuedOn, #Details)
Here's the Dapper code
var messageDetails = JsonConvert.SerializeObject(data);
var auditRecord = new
{
TypeName = data.GetType().Name,
IssuedBy = _principal.UserId(),
IssuedOn = DateTimeOffset.UtcNow,
Details = messageDetails
};
var tenant = _tenantSettingsFactory.GetCurrentTenant();
using (var sqlConnection = new SqlConnection(tenant.DbConnection))
{
await sqlConnection.OpenAsync();
await sqlConnection.ExecuteAsync(AUDIT_INSERT_SQL, auditRecord);//, transaction);
}
_principle.UserId() returns a Guid and the particular user id that exists in both tables.
When I try to run that query I get a timeout if I pass the guid as lower case. If I pass it upper case, the code works. The id is stored in the database as upper case. I've been able to replicate the same issue in SSMS. When id is passed upper cased the record inserts, when lower it times out.
Here is the stack trace.
System.Data.SqlClient.SqlException (0x80131904): Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
---> System.ComponentModel.Win32Exception (258): The wait operation timed out.
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at System.Data.SqlClient.TdsParserStateObject.ThrowExceptionAndWarning(Boolean callerHasConnectionLock, Boolean asyncClose)
at System.Data.SqlClient.TdsParserStateObject.CheckThrowSNIException()
at System.Data.SqlClient.SqlCommand.CheckThrowSNIException()
at System.Data.SqlClient.SqlCommand.EndExecuteNonQueryInternal(IAsyncResult asyncResult)
at System.Data.SqlClient.SqlCommand.EndExecuteNonQuery(IAsyncResult asyncResult)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
at Dapper.SqlMapper.ExecuteImplAsync(IDbConnection cnn, CommandDefinition command, Object param) in /_/Dapper/SqlMapper.Async.cs:line 678
at Vortext.RCM.Data.SQL.AuditStore.Append(Object data) in C:\dev\vortext-main-new\vortext-web\Vortext.RCM.Data\SQL\AuditStore.cs:line 48
at Vortext.Common.Domain.Decorators.CommandStoreDecorator`1.HandleAsync(TCommand command)
at Vortext.RCM.Common.Decorators.TransactionCommandDecorator`1.HandleAsync(TCommand command) in C:\dev\vortext-main-new\vortext-web\Vortext.RCM\Common\Decorators\TransactionCommandDecorator.cs:line 23
at CallSite.Target(Closure , CallSite , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at Vortext.RCM.Api.CompositionRoot.CommandHandlerMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) in C:\dev\vortext-main-new\vortext-web\Vortext.RCM.Api\CompositionRoot\CommandHandlerMiddleware.cs:line 52
Any ideas?
--------------UPDATE----------------
It seems that the cause is a LCK_M_S lock. I think because the id that is being written to IssuedBy is the same Id that is being modified on the UserDetails table the first transaction is blocking the second.

it turns out that the real issue is that I am trying to run a separate connection/transaction for the audit records than the main transaction that edited the user. Because the first transaction audits the UserDetails table while the second transaction is trying to update AuditRecords where the FK matches the row being edited in UserDetails, the second transaction times out waiting for the first transaction to complete. Removing the FK solves the issue.

Related

Why columns value change into NULL when try to update only one column?

This is my table which I created in sql server...
CREATE TABLE [dbo].[Addresses_Table](
[AddressID] [int] IDENTITY(1,1) NOT NULL,
[BuildingName] [varchar](300) NULL,
[UnitNumber] [nvarchar](50) NULL,
[StreetNumber] [varchar](20) NULL,
[StreetName] [varchar](200) NULL,
[Suburb] [varchar](100) NULL,
[POBox] [varchar](20) NULL,
CONSTRAINT [PK_Addresses_Table] PRIMARY KEY CLUSTERED (
[AddressID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF) ON [PRIMARY] ) ON [PRIMARY]
INSERT INTO [dbo].[Addresses_Table] (BuildingName,UnitNumber,StreetNumber, StreetName, Suburb) VALUES ('mybuilding', '101', '12','Street 1', 'TEST12')
When I try to update 'POBox' column value into '1234' (any value),
BuildingName, UnitNumber, StreetNumber, StreetName turn into NULL values.
I have attached my sql update query and results of it.
Please help me out to solve this problem....
It seems there is a trigger on the table that sets StreetName to NULL after the update. This is evidenced by the SSMS output that shows 2 rowcount messages, one when the row is updated directly and the other when the same row is updated by the trigger.
The trigger makes sense from a data perspective since StreetName does not apply to a PO box address.

SQLServer: Object reference not set to an instance of an object

Here is a screenshot of the error I'm getting.
Here is the snippet I am tying to run
USE [Warehouse_PCL]
GO
/****** Object: Table [dbo].[RouteTable] Script Date: 2/19/2018 2:27:57 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[RouteTable](
[BranchID] [int] NOT NULL,
[StoreID] [int] NOT NULL,
[WaveGroup] [int] NOT NULL,
[Wave] [int] NOT NULL,
[Aisle] [int] NOT NULL,
[Lane] [int] NOT NULL,
CONSTRAINT [PK_RouteTable] PRIMARY KEY CLUSTERED
(
[BranchID] ASC,
[StoreID] ASC,
[WaveGroup] ASC,
[Wave] ASC,
[Aisle] 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
I am unsure what is causing this, any thouhts? Let me know if there is any other information I can provide to help.
===================================
Cannot execute script.
===================================
Object reference not set to an instance of an object. (Microsoft.VisualStudio.Editor.Implementation)
------------------------------
Program Location:
at Microsoft.VisualStudio.Editor.Implementation.VsTextViewAdapter.SetScrollPosition(Int32 iBar, Int32 iFirstVisibleUnit)
at Microsoft.SqlServer.Management.UI.VSIntegration.Editors.VSTextEditorTabPage.Clear()
at Microsoft.SqlServer.Management.UI.VSIntegration.Editors.DisplaySQLResultsControl.Clear()
at Microsoft.SqlServer.Management.UI.VSIntegration.Editors.DisplaySQLResultsControl.PrepareForExecution(Boolean prepareForParse)
at Microsoft.SqlServer.Management.UI.VSIntegration.Editors.ScriptAndResultsEditorControl.StandardPrepareBeforeExecute(QEStatusBarKnownStates newStatusBarState)
at Microsoft.SqlServer.Management.UI.VSIntegration.Editors.SqlScriptEditorControl.StandardPrepareBeforeExecute(QEStatusBarKnownStates newStatusBarState)
at Microsoft.SqlServer.Management.UI.VSIntegration.Editors.ScriptAndResultsEditorControl.OnExecScript(Object sender, EventArgs a)
This thread suggests that the problem is related to the .NET Framework update KB4055532. Try the workarounds suggested here.

Clustered Index Update Slow Update On Large Table

I am having a problem updating a large table with millions of rows please advice to reduce the update time.
Table definition
CREATE TABLE [dbo].[tbl_sms_job_detail](
[JobDetailID] [int] IDENTITY(1,1) NOT NULL,
[JobID] [int] NULL,
[DistributorID] [int] NULL,
[ResellerID] [int] NULL,
[CustomerID] [int] NULL,
[SenderID] [nvarchar](50) NULL,
[PhoneNumber] [nvarchar](100) NULL,
[SMSMessage] [nvarchar](1000) NULL,
[MessageType] [nvarchar](50) NULL,
[MessageLength] [int] NULL,
[MessageParts] [int] NULL,
[ClientRate] [decimal](18, 5) NULL,
[ClientCost] [decimal](18, 5) NULL,
[ResellerRate] [decimal](18, 5) NULL,
[ResellerCost] [decimal](18, 5) NULL,
[DistributorRate] [decimal](18, 5) NULL,
[DistributorCost] [decimal](18, 5) NULL,
[RouteDetailID] [int] NULL,
[SMSID] [nvarchar](200) NULL,
[DLRStatus] [nvarchar](100) NULL,
[ErrorCode] [int] NULL,
[ErrorDescription] [nvarchar](2000) NULL,
[SentDate] [datetime] NULL,
[SentDateUTC] [datetime] NULL,
[SMSSource] [nvarchar](50) NULL,
[SMSType] [nvarchar](100) NULL,
[APISMSID] [int] NULL,
[DLRDate] [datetime] NULL,
[DLRDateUTC] [datetime] NULL,
CONSTRAINT [PK_tbl_sms_job_detail] PRIMARY KEY CLUSTERED
(
[JobDetailID] 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 NONCLUSTERED INDEX [NonClusteredIndex-20170919-173756] ON [dbo].[tbl_sms_job_detail] ( [JobID] ASC, [DLRStatus] 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) GO
CREATE NONCLUSTERED INDEX [NonClusteredIndex-20170919-174142] ON [dbo].[tbl_sms_job_detail]
(
[SMSID] 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)
GO
Update Procedure
CREATE Procedure [dbo].[sp_update_message_status]
#SMSID nvarchar(200),
#DLRStatus nvarchar(100),
#ErrorCode int,
#ErrorDescription nvarchar(2000)
AS
UPDATE tbl_sms_job_detail SET DLRStatus = #DLRStatus, ErrorCode = #ErrorCode, ErrorDescription = #ErrorDescription WHERE SMSID = #SMSID
Execution Plan
This Procedure is called up to 1000 times in several minutes and some of them fail to update as it takes time to update the previous record what can be done to increase the update of a record in this table.
I suspect that the issue is not being caused by the actual clustered index but by the effect the update query has.
MSSQL is a page based storage system. When adding records to the table, as the clustered index is on the field [JobDetailID] [int] IDENTITY(1,1) NOT NULL, each new record is applied to the last page currently at the table (if it will fit) or a new page is tacked onto the end of the table and the record stored in it.
Assuming that [DLRStatus] and/or [ErrorDescription] start of a null or empty strings, when the update sproc runs, it has to find some space in the page that the record is already in to store the new value in. SQL keeps a little space in each page file for such purpose, but when that space is used up, it will have to do a page split - splitting the contents of the one page file into the existing page file and a newly created blank page file. As the primary key is clustered, this new page file has to be inserted so it keeps the records stored in the table in the clustered index order. It is quite likely that this page splitting is at the root of the problem.
The amount of space that SQL keeps back before creating a new page is configurable, therefore one solution is to initially create the page files with plenty of 'expansion' room. On an index it is called the fill factor, but I am not sure what the correct term is for data pages (probably still a fill factor, but not sure).
Another alternative is to store the returned error information in a separate table and then store the primary key for the 'error information' record in table [tbl_sms_job_detail]. As long as the key is not a nvarchar / varchar (and who would do this anyway), the space required in the page file will already be reserved. Thus recording the error information requires appending the variable text information to the end of the last page file for the new table and updating a foreign key in your original table that already has space reserved for it and so doesn't trigger of a page slit.

Attempted to read or write protected memory - .NET EF + Web API

I have a relatively simple application that pulls SQL data via a .NET Web API using EF6. There are three tables in the database:
Product
CREATE TABLE [dbo].[Product]
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](255) NOT NULL,
[FullName] [varchar](max) NOT NULL,
[Description] [varchar](max) NOT NULL,
[BranchID] [int] NOT NULL,
[ProgramID] [int] NOT NULL,
[TechnologyPlatformID] [int] NOT NULL,
[StatusID] [int] NOT NULL,
[FunctionID] [int] NOT NULL,
[ProgramManagerID] [int] NOT NULL,
[TypeID] [int] NOT NULL,
[Vendor] [varchar](max) NOT NULL,
[VendorPOC] [varchar](max) NOT NULL,
[URL] [varchar](255) NULL,
[Code] [varchar](50) NULL,
[CreatedBy] [int] NOT NULL,
[CreateDate] [datetime] NOT NULL,
[ModifiedBy] [int] NOT NULL,
[ModifiedDate] [datetime] NOT NULL,
CONSTRAINT [PK_Product]
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_PADDING OFF
GO
ALTER TABLE [dbo].[Product] WITH CHECK
ADD CONSTRAINT [FK_Product_Function]
FOREIGN KEY([FunctionID]) REFERENCES [dbo].[Function] ([ID])
GO
ALTER TABLE [dbo].[Product] CHECK CONSTRAINT [FK_Product_Function]
GO
ALTER TABLE [dbo].[Product] WITH CHECK
ADD CONSTRAINT [FK_Product_Program]
FOREIGN KEY([ProgramID]) REFERENCES [dbo].[Program] ([ID])
GO
ALTER TABLE [dbo].[Product] CHECK CONSTRAINT [FK_Product_Program]
GO
Program:
CREATE TABLE [dbo].[Program]
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](255) NOT NULL,
CONSTRAINT [PK_Program]
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
Function:
CREATE TABLE [dbo].[Function]
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](255) NOT NULL,
[Description] [varchar](max) NOT NULL,
CONSTRAINT [PK_Function_1]
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
My EDMX looks normal:
And here's how I'm accessing the data in my repo:
Suddenly I'm getting the following error when calling GetProducts():
An unhandled exception of type 'System.AccessViolationException' occurred in Unknown Module.
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
I can't seem to figure out what's causing this. Here's what I have tried:
Made sure "Suppress JIT optimization..." was unchecked in VS
Repaired .NET Framework on my local machine
Neither worked...however, if I delete the Function table in SQL and update my EDMX, the issue is resolved. Why would this table be causing the issue?
Appreciate any input, thank you!
Try turning proxy generation off, and see if you still get the same problem.
My initial guess would be that you are including the Program directly via .Include(x => x.Program), but Function navigation property is being proxied into a lazy property. And when WebAPI tries to serialize it, it throws an error.

How to Insert into 2 Tables ProductOrder and ProductOrderLine using VBA & Foreign Keys in Excel

I am newbiew using VBA/FK/SQL server all in one. I am creating simple purchase order workbook user interface in excel.
I have created two tables:
CREATE TABLE [dbo].[PurchaseOrder](
[PKPurchaseOrderID] [bigint] IDENTITY(1,1) NOT NULL,
[PurchaseOrderNumber] [bigint] NULL,
[PurchaseOrderDate] [date] NULL,
[PurchaseOrderTime] [int] NULL,
[PurchaseOrderSupplierID] [nvarchar](50) NULL,
[ShipToA1] [nvarchar](50) NULL,
[ShipToA2] [nvarchar](50) NULL,
[ShipToA3] [nvarchar](50) NULL,
[ShipToA4] [nvarchar](50) NULL,
CONSTRAINT [PK_PurchaseOrder] PRIMARY KEY CLUSTERED
(
[PKPurchaseOrderID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
and
CREATE TABLE [dbo].[PurchaseOrderLines](
[PKPurchaseOrderLineID] [bigint] IDENTITY(1,1) NOT NULL,
[FKPurchaseOrderID] [bigint] NULL,
[Quantity] [smallint] NULL,
[Item] [nchar](25) NULL,
[Description] [nvarchar](50) NULL,
[siteID] [nchar](10) NULL,
[UnitPrice] [money] NULL,
[LineTotal] [money] NULL,
CONSTRAINT [PK_PurchaseOrderLines] PRIMARY KEY CLUSTERED
(
[PKPurchaseOrderLineID] 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].[PurchaseOrderLines] WITH CHECK ADD CONSTRAINT
[FK_PurchaseOrderLines_PurchaseOrder] FOREIGN KEY([FKPurchaseOrderID])
REFERENCES [dbo].[PurchaseOrder] ([PKPurchaseOrderID])
ALTER TABLE [dbo].[PurchaseOrderLines] CHECK CONSTRAINT
[FK_PurchaseOrderLines_PurchaseOrder]
GO
I want to achieve that in the background when user clicks the button both tables are updated.
I am not sure how I can link brand new row created in the PurchaseOrder table with FK in the PurchaseorderLine table.
What i plan to do for single user interface:
Insert New Order
Use Max(PKPurchaseOrderID) as FK for new order lines table.
How can I determine currently inserted Order ID(PKPurchaseOrderID) if multiple users are working/submitting orders at the same time. I am afraid order lines may be assigned to different orders if I use my plan. e.g.
Please advise.
I use SQL Server 2008 and Excel 2007/2010
Many thanks
I would create a stored procedure that inserts the new row and returns the ID with SCOPE_IDENTITY()
Here's a decent article on the different "identity" methods in SQL Server.
http://blog.sqlauthority.com/2007/03/25/sql-server-identity-vs-scope_identity-vs-ident_current-retrieve-last-inserted-identity-of-record/