Saving server date and time - c#

I want to save the time and date within my news but in the method below I save the time of the user and if his/her time is wrong, the wrong time will be save. How can I use the server's time instead.
SqlConnection sqlconn = new SqlConnection(connStr);
SqlCommand sqlcmd = new SqlCommand("insert into SubmitManuscript(username,title,authors,type,date,upload,reviewer1,email1,reviewer2,email2,reviewer3,email3)values(#username,#title,#authors,#type,#date,#upload,#reviewer1,#email1,#reviewer2,#email2,#reviewer3,#email3)", sqlconn);
sqlcmd.Parameters.AddWithValue("#username", username);
sqlcmd.Parameters.AddWithValue("#title", Text_Title.Text);
sqlcmd.Parameters.AddWithValue("#authors", Text_Author.Text);
sqlcmd.Parameters.AddWithValue("#type", dd_Type.SelectedItem.Text);
sqlcmd.Parameters.AddWithValue("#date", DateTime.Now);
//sqlcmd.Parameters.AddWithValue("#upload", "~/Suppelment/" +

There is no need to pass datetime parameter. Just set a datetime as default value in your table in the Database. That should do the trick.
Here is a link how to set this in table generation script:
How to set the default value for a datetime column
Edit: Your table needs to have a special DateTimeStamp column that will set system-datetime automatically when you insert a record. I am putting a simple script that you may use as an example.
Note: If you already have table in place then just start from script ALTER TABLE
CREATE TABLE [dbo].[Employee]
(
[EmployeeId] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NULL,
[BirthDate] [datetime] NOT NULL,
[LastUpdateTime] [datetime] NOT NULL,
CONSTRAINT [PK_Employee]
PRIMARY KEY CLUSTERED ([EmployeeId] 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].[Employee]
ADD CONSTRAINT [DF_Employee_LastUpdateTime]
DEFAULT (getdate()) FOR [LastUpdateTime]
GO
--- You may also use multiple record insert statement in SQL Server 2008
--- however, I will use a traditional approach here
INSERT INTO [dbo].[Employee] (Name, BirthDate)
VALUES ('Smith', '04/14/1979')
INSERT INTO [dbo].[Employee] (Name, BirthDate)
VALUES ('Jhone', '11/08/1983')
GO

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.

writing enum value to db col

I'm using what I consider to be very standard C# and T-SQL code to populate a column of datatype char(1) based on a C# enum with char values :
I am seeing an asterisk * written to db when a C should be written -- but I have been unable to find a consistent repo and I have no idea how this could happen.
Some questions are how could a row be inserted into my db that includes a value not present in my enum ? Does the asterisk have any special meaning in this context ?
Here's representative code - stripped-down for readability :
CREATE TABLE [MY_TABLE](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[STATUS] [char](1) NOT 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] TEXTIMAGE_ON [PRIMARY]
CREATE PROCEDURE [INSERT_TO_MY_TABLE]
(
#status [char](1)
)
AS
BEGIN
INSERT INTO [MY_TABLE]
(
[STATUS]
)
VALUES
(
#status
)
END
public enum Status
{
Adult = 'A',
Juvenile = 'J',
Child = 'C'
}
Statu status = Status.Child;
using (var command = connection.CreateCommand())
{
command.CommandText = $"INSERT_TO_MY_TABLE";
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter($"#status", (char)status));
command.ExecuteNonQuery();
}
It looks like you have Status and StatusEnum active in your code - two different unrelated Enums
You want to change StatusEnum to Status
Also a string cast could generate the value "Child" instead of 'C' as an FYI.
status.ToString().Substring(0, 1) - would pull the first char of "Child" not the value of 'C'

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

Inserting data with Dapper with DateTime2 throws SqlDateTime overflow exception

If I have an object such as:
public class Person
{
public int Id {get;set;}
public string Name {get;set;}
public DateTime DOB {get;set;}
}
If I set the name on my object and DOB is DateTime.MinValue and use Dapper like so:
INSERT INTO [Person] ([Person].[Name], [Person].[DOB]) VALUES (#Name, #DOB);
SELECT CAST(SCOPE_IDENTITY() AS BIGINT) AS [Id]
connection.Query<long>(sql, entity);
This throws SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM.
However if I execute the SQL in SQL Management Studio with a string version '0001-01-01 00:00:00' it inserts into the db fine.
Any ideas how to get this to work?
Thanks
UPDATE:
CREATE TABLE [dbo].[Person](
[Id] [int] IDENTITY(1,1) NOT NULL,
[DOB] [datetime2](7) NULL,
[Name] [nvarchar](20) NOT NULL,
CONSTRAINT [PK_Referrer_Referee] 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
.Net DateTime should handle both.
Dapper is mapping datetime to DbType DateTime and not DbType.DateTime2 which is what you need.
https://github.com/SamSaffron/dapper-dot-net/blob/master/Dapper%20NET40/SqlMapper.cs#L384
typeMap[typeof(DateTime)] = DbType.DateTime;
typeMap[typeof(DateTime?)] = DbType.DateTime;
But you can add a TypeMap yourself but then you need to create a datetime2 type/class.
Try looking at this SO answer, about mapping the DateTime2 type in Dapper
Issue is within insert statement. You have specified three values and two column names. Query like this will work or add column name corresponding to variable #RefereeId.
INSERT INTO [Person] ([Person].[Name], [Person].[DOB]) VALUES (#Name, #DOB);

SQL SELECT From two tables (friendship) statement

I have the following tables created:
Table #1: tbl_Connections
USE [taaraf_db]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[tbl_Connections](
[uc_Id] [int] IDENTITY(1,1) NOT NULL,
[uc_User] [nvarchar](50) NOT NULL,
[uc_Connection] [nvarchar](50) NOT NULL,
[uc_IsPending] [int] NOT NULL,
[uc_DateTime] [datetime] NOT NULL,
CONSTRAINT [PK_tbl_Connections] PRIMARY KEY CLUSTERED
(
[uc_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].[tbl_Connections] ADD CONSTRAINT [DF_tbl_Connections_uc_IsPending] DEFAULT ((1)) FOR [uc_IsPending]
GO
Table #2: tbl_LiveStream
USE [taaraf_db]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[tbl_LiveStreams](
[ls_Id] [int] IDENTITY(1,1) NOT NULL,
[ls_Story] [nvarchar](max) NOT NULL,
[ls_User] [nvarchar](50) NOT NULL,
[ls_Connection] [nvarchar](50) NOT NULL,
[ls_DateTime] [datetime] NOT NULL,
CONSTRAINT [PK_tbl_LiveStreams] PRIMARY KEY CLUSTERED
(
[ls_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 uc_User in tbl_Connections represents the user who initiated a friend request, and uc_Connection
represents the other party.
Same concept is applied on the second table (tbl_LiveStreams)
I am trying to select all new LiveStreams for a cetrain user, LiveStream should be retrieved for a specific user only if that user is connected to the other party (uc_IsPending = 0)
I have a C# function that takes the following arguments:
public static DataTable GetAsyncLiveStream(string CurrentUser, int startAt, int howMany) { ... }
And with the above, a DataTable should return all new items in LiveStream for the given CurrentUser (ls_User) if the requirements specified above are true.
This is sort of like the Facebook news feed, what's happening with friends etc...
Oh yeah, tbl_LiveStream is populated whenever someone (ls_User) initates some sort of specific event to (ls_Connection).
I'm not sure if i'm complicating my life here but that's what I have and all help is appreciated.
I should mention that I've done this by looping through all returned records from tbl_LiveStream and done some validation using a custom class function .IsFriends() that will go and check for friendship status in the database and programatically populates a DataTable... Which is sort of stupid, I admit. But I'm not sure how to do this.
One last thing,
I'm using the following query to return limited results:
SELECT * FROM (
SELECT row_number() OVER (ORDER BY ) AS rownum, ls_Id
FROM )
AS A
WHERE A.rownum BETWEEN (#start) AND (#start + #rowsperpage)
Please help and thank you for your time.
EDIT
I'd like to note that this is how I am fetching who's friends with who from the tbl_Connections Table.
const string sql = "SELECT REPLACE((uc_Connection + uc_User), #CurrentUser, '') AS Connection " +
"FROM tbl_Connections Connection " +
"WHERE (#CurrentUser = uc_Connection) OR (#CurrentUser = uc_User)";
SELECT * FROM (
SELECT row_number() OVER (ORDER BY ) AS rownum, ls_Id
FROM )
AS A
WHERE A.rownum BETWEEN (#start) AND (#start + #rowsperpage)
This syntax is wrong. You can't do it like that. Use a Union, or use LINQ to SQL.
From a critique perspective, don't get DataTables, get Entities. You seem to be over complicating quite a bit here, with technologies you may not be familiar with. I'd advise taking all currently existing data and dumping it to a CSV file, then starting the application from scratch with something like Sharp Architecture, which can abstract away some of these details for you.

Categories