Update only the edited fields in a C# application - c#

I have a big table in my SQL Server database as follows:
CREATE TABLE [dbo].[Servers](
[ServerId] [uniqueidentifier] NOT NULL,
[ServerName] [nvarchar](50) NULL,
[HostName] [nvarchar](50) NULL,
[OperatingSystem] [nvarchar](50) NULL,
[OSVersion] [nvarchar](50) NULL,
[OSComment] [nvarchar](200) NULL,
[ServerManufacturer] [nvarchar](50) NULL,
[ServerModel] [nvarchar](50) NULL,
[IP] [binary](4) NULL,
[Mask] [binary](4) NULL,
[Gateway] [binary](4) NULL,
[PrimaryDNS] [binary](4) NULL,
[SecondaryDNS] [binary](4) NULL,
[NetworkType] [nvarchar](20) NULL,
[NetworkComment] [nvarchar](200) NULL,
[SiteId] [uniqueidentifier] NULL,
[DataCenterRow] [smallint] NULL,
[DataCenterRack] [smallint] NULL,
[AntiVirusProduct] [nvarchar](50) NULL,
[AntiVirusVersion] [nvarchar](50) NULL,
[AntiVirusComment] [nvarchar](200) NULL,
[PassedOSSecurity] [nvarchar](50) NULL,
[Approved] [bit] NULL,
[ApprovedBy] [nvarchar](50) NULL,
CONSTRAINT [PK_Servers] PRIMARY KEY CLUSTERED
(
[ServerId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
In my C# Windows Forms application I have a form that displays the contents of this table and performs Display/Create/Delete/Update operation.
Now when I edit certain fields in a record I need to performs a query that will update only the fields which has been updated. In other words, I need a query that will dynamically identify the edited fields and update them.
The stored procedure that updates the columns one by one looks like this:
CREATE PROCEDURE dbo.UpdateServer #ServerName nvarchar(50), #HostName nvarchar(50),#OperatingSystem nvarchar(50),
#OSVersion nvarchar(50), #OSComment nvarchar(50),#ServerManufacturer nvarchar(50),
#ServerModel nvarchar(50), #IP nvarchar(15),#Mask nvarchar(15), #Gateway nvarchar(15),
#PrimaryDNS nvarchar(15), #SecondaryDNS nvarchar(15), #NetworkType nvarchar(20),#NetworkComment nvarchar(200),
#SiteId uniqueidentifier, #DataCenterRow smallint, #DataCenterRack smallint, #AntiVirusProduct nvarchar(50),
#AntiVirusVersion nvarchar(50), #AntiVirusComment nvarchar(200), #PassedOSSecurity bit, #Approved bit,
#ApprovedBy nvarchar(50)
AS
UPDATE [SystemsInfo].[dbo].[Servers]
SET ServerName=#ServerName,HostName=#HostName,OperatingSystem=#OperatingSystem,OSVersion=#OSVersion,OSComment=#OSComment,ServerManufacturer=#ServerManufacturer,ServerModel=#ServerModel,IP=(select dbo.fnBinaryIPv4(#IP)),
Mask=(select dbo.fnBinaryIPv4(#Mask)),Gateway=(select dbo.fnBinaryIPv4(#Gateway)),PrimaryDNS=(select dbo.fnBinaryIPv4(#PrimaryDNS)),SecondaryDNS=(select dbo.fnBinaryIPv4(#SecondaryDNS)),
NetworkType=#NetworkType,NetworkComment=#NetworkComment,SiteId=#SiteId,
DataCenterRow=#DataCenterRow, DataCenterRack=#DataCenterRack, AntiVirusProduct=#AntiVirusProduct, AntiVirusVersion=#AntiVirusVersion, AntiVirusComment=#AntiVirusComment, PassedOSSecurity=#PassedOSSecurity,
Approved=#Approved,ApprovedBy=#ApprovedBy;

I think the comment provided by Steve is the main way.
But, another option is to track the fields edited by user in your UI (eg. CellEndEdit or CellValueChanged), and create the dynamic sql query in your c# code (using a StringBuilder and SqlParameters) and finally execute it.

Related

How do I use Dapper to insert a list<myobject> as parameter to a stored procedure

I have a SQL Server table with 10 columns:
CREATE TABLE [bank].[CommonPostingsFromBankFiles]
(
[Id] [INT] IDENTITY(1,1) NOT NULL,
[BankRegistrationNumber] [INT] NOT NULL,
[BankAccountNumber] [BIGINT] NOT NULL,
[BankName] [NVARCHAR](50) NULL,
[BankAccount] [NVARCHAR](50) NULL,
[PostingAmount] [DECIMAL](18, 2) NOT NULL,
[PostingDate] [DATE] NOT NULL,
[Primo] [CHAR](1) NULL,
[PostingText] [NVARCHAR](100) NULL,
[HideThisRecord] [BIT] NULL,
CONSTRAINT [PK_CommonPostingsFromBankFiles]
PRIMARY KEY CLUSTERED ([BankRegistrationNumber] ASC,
[BankAccountNumber] ASC,
[PostingAmount] ASC,
[PostingDate] 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]
)
and a stored procedure that takes 7 parameters:
ALTER PROCEDURE [bank].[spInsertCommonPostings]
(#BankRegistrationNumber INT,
#BankAccountNumber BIGINT,
#BankName NVARCHAR(50),
#PostingAmount DECIMAL(18, 2),
#PostingDate DATE,
#Primo CHAR(1),
#PostingText NVARCHAR(100))
AS
BEGIN
IF NOT EXISTS (SELECT *
FROM bank.CommonPostingsFromBankFiles
WHERE BankRegistrationNumber = #BankRegistrationNumber
AND BankAccountNumber = #BankAccountNumber
AND BankName = #BankName
AND PostingAmount = #PostingAmount
AND PostingDate = #PostingDate)
INSERT INTO bank.CommonPostingsFromBankFiles (BankRegistrationNumber, BankAccountNumber,
BankName, PostingAmount,
PostingDate, Primo, PostingText)
VALUES (#BankRegistrationNumber, #BankAccountNumber,
#BankName, #PostingAmount,
#PostingDate, #Primo, #PostingText);
END;
What I want is to use Dapper to write a List<Postings> to the table using the stored procedure.
I have searched and searched but found no example that helped me.
If I do a
connection.Execute(sql: "spMyStoredProc", MyList, commandType: CommandType.StoredProcedure);
I get an error
Procedure or function spMyStoredProc has too many arguments specified
If I replace the name of the stored procedure with the sql from the stored procedure and set CommandType to Text it works as expected.
Could anybody please post me an example showing how to insert my list using my stored procedure.
Thanks,
Steffen
Simplistically, and assuming the names of the properties in your c# object are identical to the names of the parameters in your stored proc, you could:
MyList.ForEach(x => connection.Execute(sql: "spMyStoredProc", x, commandType: CommandType.StoredProcedure));
If the param/props aren't aligned it may be simplest to provide an anonymous type populated with values from x that covers them
MyList.ForEach(x => connection.Execute(
sql: "spMyStoredProc",
new { BankRegistrationNumber = x.BankRN, ... },
commandType: CommandType.StoredProcedure
));
For a list of 10 objects it will invoke the proc 10 times; it's not the fastest way to do it, but I don't think you've stated any particular goals re performance etc.

Unable to fetch data using SQL Server datalength function due to performance issues

I have a documents table in my database. The document table structure is like
CREATE TABLE [dbo].[Documents]
(
[DocumentId] [BIGINT] NOT NULL IDENTITY(1, 1),
[ObjectType] [VARCHAR](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[ObjectId] [BIGINT] NOT NULL,
[DocumentName] [VARCHAR](250) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[DocumentFile] [VARBINARY](MAX) NOT NULL,
[isTemp] [BIT] NOT NULL CONSTRAINT [DF_Documents_isTemp] DEFAULT ((0)),
[IsActive] [BIT] NOT NULL,
[RowGuid] [UNIQUEIDENTIFIER] NOT NULL CONSTRAINT [DF_Documents_RowGuid] DEFAULT (newid()),
[CreatedBy] [BIGINT] NOT NULL,
[CreatedOn] [DATETIME] NOT NULL,
[UpdatedBy] [BIGINT] NULL,
[UpdatedOn] [DATETIME] NULL
)
GO
-- Constraints and Indexes
ALTER TABLE [dbo].[Documents]
ADD CONSTRAINT [PK_Documents]
PRIMARY KEY CLUSTERED ([DocumentId])
GO
CREATE NONCLUSTERED INDEX [ix_DocumentName]
ON [dbo].[Documents] ([DocumentName])
GO
CREATE NONCLUSTERED INDEX [ix_ObjectId]
ON [dbo].[Documents] ([ObjectId])
GO
CREATE NONCLUSTERED INDEX [ix_ObjectType]
ON [dbo].[Documents] ([ObjectType])
GO
In the documents table there are 100k records.
This is the C# method which is fetching single document on the basis of objectid.
public IQueryable<Document> GetDocumentData(long objectId, string objectType)
{
var searchResults = new MerrickEntities().Documents.Where(c => c.ObjectId == objectId && c.ObjectType == objectType && SqlFunctions.DataLength(c.DocumentFile) > 0);
return searchResults.AsQueryable();
}
In this query is not fetching data and it seems the issue is caused by datalength function.
How can I optimize this query?

'Help' The primary key column cannot be generated by the server

My create table code like :
CREATE TABLE [dbo].[DeTai](
[ID] [int] IDENTITY(1,1) NOT NULL,
[MaDeTai] AS ('DT'+right('000000'+CONVERT([varchar](10),[ID]),(6))) PERSISTED NOT NULL,
[TenDeTai] [nvarchar](255) NOT NULL,
[LinhVuc] [nvarchar](255) NOT NULL,
[Nam] [int] NOT NULL,
[MaGV] [varchar](8) NOT NULL,
)
When I use linq to sql to insert a values this messages come out
The primary key column of type 'VarChar(8)' cannot be generated by the server.
what should i do ?
you have to designate the primary key, setting identity is not enough
CREATE TABLE [dbo].[DeTai](
[ID] [int] IDENTITY(1,1) NOT NULL,
[MaDeTai] AS ('DT'+right('000000'+CONVERT([varchar](10),[ID]),(6))) PERSISTED NOT NULL,
[TenDeTai] [nvarchar](255) NOT NULL,
[LinhVuc] [nvarchar](255) NOT NULL,
[Nam] [int] NOT NULL,
[MaGV] [varchar](8) NOT NULL,
constraint PK_DeTail_ID primary key (ID)
)

NLog DatabaseTarget Install not working

Am using NLog 4.2.2 and asp net 5. All my NLog configurations are on code. I need to deploy my project and want to make sure the appropriate SqlServer Table and StoredProcedure are created. I'm using the DatabaseTarget.Install() method like this:
dbTarget.InstallDdlCommands.Clear();
dbTarget.InstallDdlCommands.Add(new DatabaseCommandInfo
{
ConnectionString = connectionString,
CommandType = System.Data.CommandType.Text,
IgnoreFailures = false,
Text = $#"CREATE TABLE [dbo].[{TableName}] (
[ID] [int] IDENTITY(1,1) NOT NULL,
[MachineName] [nvarchar](200) NULL,
[SiteName] [nvarchar](200) NOT NULL,
[Logged] [datetime] NOT NULL,
[Level] [varchar](5) NOT NULL,
[UserName] [nvarchar](200) NULL,
[Message] [nvarchar](max) NOT NULL,
[Logger] [nvarchar](300) NULL,
[Properties] [nvarchar](max) NULL,
[ServerName] [nvarchar](200) NULL,
[Port] [nvarchar](100) NULL,
[Url] [nvarchar](2000) NULL,
[Https] [bit] NULL,
[ServerAddress] [nvarchar](100) NULL,
[RemoteAddress] [nvarchar](100) NULL,
[Callsite] [nvarchar](300) NULL,
[Exception] [nvarchar](max) NULL,
CONSTRAINT [PK_dbo.Log] 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];"
});
dbTarget.InstallDdlCommands.Add(new DatabaseCommandInfo
{
ConnectionString = connectionString,
CommandType = System.Data.CommandType.Text,
IgnoreFailures = false,
Text = $#"CREATE PROCEDURE [dbo].[{ProcName}] (
#machineName nvarchar(200),
#siteName nvarchar(200),
#logged datetime,
#level varchar(5),
#userName nvarchar(200),
#message nvarchar(max),
#logger nvarchar(300),
#properties nvarchar(max),
#serverName nvarchar(200),
#port nvarchar(100),
#url nvarchar(2000),
#https bit,
#serverAddress nvarchar(100),
#remoteAddress nvarchar(100),
#callSite nvarchar(300),
#exception nvarchar(max)
) AS
BEGIN
INSERT INTO [dbo].[{TableName}] (
[MachineName],
[SiteName],
[Logged],
[Level],
[UserName],
[Message],
[Logger],
[Properties],
[ServerName],
[Port],
[Url],
[Https],
[ServerAddress],
[RemoteAddress],
[CallSite],
[Exception]
) VALUES (
#machineName,
#siteName,
#logged,
#level,
#userName,
#message,
#logger,
#properties,
#serverName,
#port,
#url,
#https,
#serverAddress,
#remoteAddress,
#callSite,
#exception
);
END"
});
using (var context = new InstallationContext())
{
if (dbTarget.IsInstalled(context) != true)
dbTarget.Install(context);
}
But when I run my code I get this exception
I have seen this question and I think I'm doing what they say but still doesn't work for me. I know the rest of the code to be good as DB logging works just fine once I manually create the Table and StoredProcedure
After a while I opened an issue in github and I got the answer from there. Turns out that, as of now, when you programmatically create a configuration file (as I was) you have to manually call configuration.Install(installationContext) in order for the different Targets to be actually initialized, as a side effect it will also run the Install method of the Targets that have it. So all the above code needs to do is
// Target configuration as is (except for the installation part)
config.AddTarget(dbTarget);
using(var context = new InstallationContext())
{
config.Install(context);
}
if there are more than one target though I think config.Install(context) should be called after all target (or at least most of them) have being added as it initializes all registered targets and runs Install on them.

SharePoint Foundation 2013 IMPORT\EXPORT dbo.allDocs file\files

I would like to import\export file from Sharepoint 2013 database via C#. Do you know how to do it? Because file in SharePoint is encrypted.
My question is: How import\export file in C# from SharePoint Foundation 2013 database?
CREATE SCRIPT [dbo].[AllDocs]
CREATE TABLE [dbo].[AllDocs](
[Id] [uniqueidentifier] NOT NULL,
[SiteId] [uniqueidentifier] NOT NULL,
[DirName] [nvarchar](256) NOT NULL,
[LeafName] [nvarchar](128) NOT NULL,
[Level] [tinyint] NOT NULL,
[ParentId] [uniqueidentifier] NOT NULL,
[DeleteTransactionId] [varbinary](16) NOT NULL,
[WebId] [uniqueidentifier] NOT NULL,
[ListId] [uniqueidentifier] NULL,
[DoclibRowId] [int] NULL,
[Type] [tinyint] NOT NULL,
[SortBehavior] [tinyint] NOT NULL,
[Size] [int] NULL,
[ETagVersion] AS (case when [InternalVersion] IS NULL then NULL else ([InternalVersion]+[BumpVersion]*(256))/(256) end),
[EffectiveVersion] AS (case when [InternalVersion] IS NULL then NULL else [InternalVersion]+[BumpVersion]*(256) end),
[InternalVersion] [int] NULL,
[ContentVersion] [int] NOT NULL,
[NextBSN] [bigint] NULL,
[MetadataNextBSN] [bigint] NULL,
[StreamSchema] [tinyint] NULL,
[HasStream] AS (case when [Type]=(0) AND ([DocFlags]&(256))=(256) AND [SetupPath] IS NULL OR [SetupPath] IS NOT NULL AND ([DocFlags]&(64))=(64) then (1) else (0) end),
[BumpVersion] [tinyint] NOT NULL,
[UIVersion] [int] NOT NULL,
[Dirty] AS (case when [BumpVersion]<>(0) then CONVERT([bit],(1)) else CONVERT([bit],(0)) end),
[ListDataDirty] [bit] NOT NULL,
[DocFlags] [int] NULL,
[ThicketFlag] [bit] NULL,
[CharSet] [int] NULL,
[ProgId] [nvarchar](255) NULL,
[TimeCreated] [datetime] NOT NULL,
[TimeLastModified] [datetime] NOT NULL,
[NextToLastTimeModified] [datetime] NULL,
[MetaInfoTimeLastModified] [datetime] NULL,
[TimeLastWritten] [datetime] NULL,
[SetupPathVersion] [tinyint] NOT NULL,
[SetupPath] [nvarchar](255) NULL,
[SetupPathUser] [nvarchar](255) NULL,
[CheckoutUserId] [int] NULL,
[DraftOwnerId] [int] NULL,
[CheckoutDate] [datetime] NULL,
[CheckoutExpires] [datetime] NULL,
[VersionCreatedSinceSTCheckout] [bit] NOT NULL,
[LTCheckoutUserId] AS (case when ([DocFlags]&(32))=(32) then [CheckoutUserId] end),
[CheckinComment] [nvarchar](1023) NULL,
[IsCheckoutToLocal] AS (case when ([DocFlags]&(512))=(512) then (1) else (0) end),
[VirusVendorID] [int] NULL,
[VirusStatus] [tinyint] NULL,
[VirusInfo] [nvarchar](255) SPARSE NULL,
[VirusInfoEx] [varbinary](max) NULL,
[MetaInfo] [dbo].[tCompressedBinary] NULL,
[MetaInfoSize] [int] NULL,
[MetaInfoVersion] [int] NOT NULL,
[UnVersionedMetaInfo] [dbo].[tCompressedBinary] NULL,
[UnVersionedMetaInfoSize] [int] NULL,
[UnVersionedMetaInfoVersion] [int] NULL,
[WelcomePageUrl] [nvarchar](260) NULL,
[WelcomePageParameters] [nvarchar](max) NULL,
[IsCurrentVersion] [bit] NOT NULL,
[AuditFlags] [int] NULL,
[InheritAuditFlags] [int] NULL,
[UIVersionString] AS ((CONVERT([nvarchar],[UIVersion]/(512))+'.')+CONVERT([nvarchar],[UIVersion]%(512))),
[ScopeId] [uniqueidentifier] NOT NULL,
[BuildDependencySet] [varbinary](max) NULL,
[ParentVersion] [int] NULL,
[ParentVersionString] AS ((CONVERT([nvarchar],[ParentVersion]/(512))+'.')+CONVERT([nvarchar],[ParentVersion]%(512))),
[TransformerId] [uniqueidentifier] NULL,
[ParentLeafName] [nvarchar](128) NULL,
[CtoOffset] [smallint] NULL,
[Extension] AS (case when charindex(N'.',[LeafName] collate Latin1_General_BIN)>(0) then right([LeafName],charindex(N'.',reverse([LeafName]) collate Latin1_General_BIN)-(1)) else N'' end),
[ExtensionForFile] AS (case when [Type]=(0) AND charindex(N'.',[LeafName] collate Latin1_General_BIN)>(0) then right([LeafName],charindex(N'.',reverse([LeafName]) collate Latin1_General_BIN)-(1)) else N'' end),
[ItemChildCount] [int] NOT NULL,
[FolderChildCount] [int] NOT NULL,
[FileFormatMetaInfo] [varbinary](max) NULL,
[FileFormatMetaInfoSize] [int] NOT NULL,
[FFMConsistent] [bit] NULL,
[ListSchemaVersion] [int] NULL,
[ClientId] [varbinary](16) NULL,
CONSTRAINT [AllDocs_ParentId] PRIMARY KEY CLUSTERED
(
[SiteId] ASC,
[DeleteTransactionId] ASC,
[ParentId] ASC,
[Id] ASC,
[Level] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = ON, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 95) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
I try use this:
1 Code:
-- To allow advanced options to be changed.
EXEC sp_configure 'show advanced options', 1
GO
-- To update the currently configured value for advanced options.
RECONFIGURE
GO
-- To enable the feature.
EXEC sp_configure 'xp_cmdshell', 1
GO
-- To update the currently configured value for this feature.
RECONFIGURE
GO
2 Code
DECLARE #Command VARCHAR(4000),
#FileID VARCHAR(128),
#MyFilename nvarchar(max)
DECLARE curFile CURSOR FOR -- Cursor for each image in table
SELECT DocId FROM [WSS_Content].[dbo].[DocStreams]
OPEN curFile
FETCH NEXT FROM curFile
INTO #FileID
WHILE (##FETCH_STATUS = 0) -- Cursor loop
BEGIN
-- Keep the bcp command on ONE LINE - SINGLE LINE!!! - broken up for presentation
SELECT #MyFilename = LeafName from [WSS_Content].[dbo].[AllDocs] WHERE Id = #FileID
SET #Command = 'bcp "SELECT Content from [WSS_Content].[dbo].[DocStreams] WHERE DocId = ''' +
#FileID + '''" queryout "C:\' +
#MyFilename+'" -T -n -Slocalhost -fC:\bcp.fmt'
PRINT #Command -- debugging
EXEC xp_cmdshell #Command -- Carry out image export to file from db table
FETCH NEXT FROM curFile
INTO #FileID
END -- cursor loop
CLOSE curFile
DEALLOCATE curFile
But I get error:
It`s simple to import\export file in C# because it's binary file SELECT Content from [WSS_Content].[dbo].[DocStreams]

Categories