Data Table Always getting empty - c#

I am trying to display report in mvc web application using rdlc. I have created data set and data table. but now report viewer always reloading continuously. when i try to figure out the problem i found this issue.
Here C# Code
private DataTable GetData(DateTime sdate, DateTime edate,string user,string sp_name)
{
DataTable oDataTable = new DataTable();
string ConStr = System.Configuration.ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
using (SqlConnection con = new SqlConnection(ConStr))
{
SqlCommand cmd = new SqlCommand("GetBalanceSheet_CurrentUser", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#SDate", SqlDbType.DateTime).Value = sdate;
cmd.Parameters.Add("#EDate", SqlDbType.DateTime).Value = edate;
cmd.Parameters.Add("#Uid", SqlDbType.VarChar).Value = user;
SqlDataAdapter oSqlDataAdapter = new SqlDataAdapter(cmd);
oSqlDataAdapter.Fill(oDataTable);
}
return oDataTable;
}
Here Sql Stored Procedure
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- GetBalanceSheet_CurrentUser '2017-09-12' ,'2017-11-12' ,'ab0eb318-de5f-4f13-a80b-7a95f678ad8a'
ALTER PROCEDURE [dbo].[GetBalanceSheet_CurrentUser]
#SDate DateTime,#EDate DateTime,#Uid VarChar(MAX)
AS
IF OBJECT_ID ('tempdb..#TEMP1') IS NOT NULL
DROP TABLE #TEMP1
IF OBJECT_ID ('tempdb..#TEMP2') IS NOT NULL
DROP TABLE #TEMP2
DECLARE #UserId VarChar(MAX)
SELECT #UserId = #Uid
SELECT ROW_NUMBER() OVER(ORDER BY Date) RNo,Description,Date,Amount,ForUser,CreatedUser,Status,ApprovedBy
INTO #TEMP1
FROM (
SELECT PEDM.ProjectExpenditureDescription AS Description , PEDM.ExpendedDate As Date,PEDM.ProjectExpenditureCost As Amount, ANU1.UserName As ForUser,ANU1.UserName As CreatedUser,PEDM.ApprovedStatus As Status,ANU2.UserName As ApprovedBy
FROM ProjectExpenditureDetailsModel PEDM
JOIN AspNetUsers ANU1
ON ANU1.Id = PEDM.CreatedUser
JOIN AspNetUsers ANU2
ON ANU2.Id = PEDM.ApprovedBy
WHERE PEDM.IsActive = 1
AND PEDM.IsDelete = 0
AND PEDM.Rejected = 0
AND PEDM.CreatedUser = #UserId
UNION ALL
SELECT OMDM.ObtainedMoneyDescription As Description,OMDM.ObtainedDate As Date,(OMDm.ObtainedMoneyAmount *-1) As Amount, ANU3.UserName As ForUser,ANU4.UserName As CreatedUser,OMDM.ApprovedStatus,ANU5.UserName As ApprovedBy
FROM ObtainedMoneyDetailsModel OMDM
JOIN AspNetUsers ANU3
ON ANU3.Id = OMDM.ForUser
JOIN AspNetUsers ANU4
ON ANU4.Id = OMDM.CreatedUser
JOIN AspNetUsers ANU5
ON ANU5.Id = OMDM.ApprovedBy
WHERE OMDM.IsActive = 1
AND OMDM.IsDelete = 0
AND OMDM.Rejected = 0
AND OMDM.ForUser = #UserId
)A
ORDER BY Date
SELECT RNo,Description,Convert (varchar(20),Date,103) AS ConvertedDate,Date,Amount,SUM(Amount) OVER (ORDER BY RNo) AS Balance,ForUser,CreatedUser,Status,ApprovedBy
INTO #TEMP2
FROM #TEMP1
SELECT RNo,Description,ConvertedDate,Date,Amount,Balance,ForUser,CreatedUser,Status,ApprovedBy
FROM #TEMP2
WHERE Date Between #SDate AND #EDate
When I execute program sql profiler indicates it hits successfully. but when i return result to data table its always getting empty.

I have executed sp manually using same parameters. it is showing 10
records.but when i call through my c# code its hitting but sql data
adapter always empty like {}
Do you execute your sp manually under the same account?
Your procedure uses datetime parameters but the literals for this parameters that you are passing in are language dependent.
Instead, you should pass them in language independent format yyyymmdd (without any separator)
Now, your login language is different from the default login of your application, this cause the date literals to be interpreted differently.
Here is an example to show you the problem. First execute it as it is, then comment set language us_english and uncomment set language British;
declare #t table (dt datetime);
insert into #t values ('20171001'), ('20171101'); -- added 1st oct + 1st nov
--set language British;
set language us_english;
declare #SDate datetime ='2017-09-12', #EDate datetime = '2017-11-12';
select *
from #t
WHERE dt Between #SDate AND #EDate;

Related

How should I get the values from the select query of the stored procedure in c#

I want the date and the name from the select query which if I run as normal query I get the results but i when I try to get the results in C# all I get is count=0. Can anyone tell me what wrong am I doing?
Here is the C# code
private List<CertificationSummary> GetLastAccessData (string taskOwner)
{
List<CertificationSummary> lastAccessedResult = new List<CertificationSummary>();
string connectionString = SqlPlusHelper.GetConnectionStringByName("MetricRepositoryDefault");
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlParameter[] sqlParams = new SqlParameter[1];
sqlParams[0] = new SqlParameter("#taskOwner", SqlDbType.NVarChar);
sqlParams[0].Value = taskOwner;
connection.Open();
SqlCommand cmd = connection.CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "GetLastAccessedCertificationData";
cmd.Parameters.AddRange(sqlParams);
cmd.ExecuteNonQuery();
}
return lastAccessedResult;
}
And here is the stored procedure:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[GetLastAccessedCertificationData]
(#taskOwner nvarchar(255))
AS
BEGIN
DECLARE #name nvarchar(100)
DECLARE #lastAccessedDate [datetime]
SELECT #name = Name
FROM CertificationReviewCycles
INNER JOIN UserReviewCycleAccess ON CertificationReviewCycles.CertificationReviewCycleID = UserReviewCycleAccess.LastAccessedReviewCycleID
WHERE USERID = #taskOwner
SELECT #lastAccessedDate = LastAccessedDate
FROM UserReviewCycleAccess
WHERE UserID = #taskOwner
CREATE TABLE #tempTable
(
name [nvarchar](255) NULL,
[LastAccessedDate] [datetime] NULL,
)
INSERT INTO #tempTable VALUES (#name, #lastAccessedDate)
SELECT TOP(1) name, LastAccessedDate
FROM #tempTable
END
GO
You are returning lastAccessedResult which is has just been set to new List<CertificationSummary>(). This list has no items, so it has a count of 0.
Use ExecuteReader instead of ExecuteNonQuery and you can then read the data returned and store them into your lastAccessedResult list.
Read here for more info.
ExecuteNonQuery will not return results, and should only be used when you don't expect rows back. This is common for UPDATE statements.
Since you're interested in reading the rows returned by the stored procedure, use ExecuteReader, e.g var reader = cmd.ExecuteReader();
See here for more:
https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqldatareader?view=dotnet-plat-ext-3.1
You're using ExecuteNonQuery, which discards any grids from the query. You need to use ExecuteReader to consume grids, but it is a lot of mess and ceremony - the API is verbose. Frankly, I'd recommend a tool like "Dapper" (freely available on NuGet), then this becomes just
private List<CertificationSummary> GetLastAccessData (string taskOwner)
{
string connectionString = SqlPlusHelper.GetConnectionStringByName("MetricRepositoryDefault");
using var connection = new SqlConnection(connectionString);
return connection.Query<CertificationSummary>(
"GetLastAccessedCertificationData",
new { taskOwner }, // <== parameters
commandType: CommandType.StoredProcedure).AsList();
}

Loop through dynamic DataSet and insert Stored Procedure

I have a DataTable in C# that I need to insert into a table. The DataTable is completely dynamic (Columns are not pre-defined). I inserted this DataTable row by row using C# code but because it is inefficient I am sending the DataTable bulk into an SQL Stored Procedure. I need the Stored Procedure to loop through the bulk, insert row by row, and return the set of invalid data.
C# code:
SqlConnection sqlConnection = getDBConnection();
SqlCommand command = sqlConnection.CreateCommand();
command.CommandType = System.Data.CommandType.StoredProcedure;
command.CommandText = "[dbo].[saveDataIntoTable]";
SqlParameter parameter = new SqlParameter();
//The parameter for the SP must be of SqlDbType.Structured
parameter.ParameterName = "#Sample";
parameter.SqlDbType = System.Data.SqlDbType.Structured;
parameter.Value = dataTable;
command.Parameters.Add(parameter);
foreach (DataRow row in dataTable.Rows)
{
System.Diagnostics.Debug.WriteLine(row.ItemArray);
if (row.ItemArray[0] == null)
{
dataTable.Rows.Remove(row);
}
}
SqlDataReader dr = command.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(dr);
//handling the dt DataTable here
Stored Procedure:
USE [DATABASE_NAME]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[saveDataIntoTable]
(
-- which accepts one table value parameter. It should be noted that the parameter is readonly
#Sample As [dbo].[SampleUserData] Readonly
)
AS
BEGIN
BEGIN TRY
Insert Into USER(USER_ID,EMAIL,PASSWORD,PASSWORD_HINT,PWD_CHANGED_DATE,
CREATED_BY,CREATED_DATE,UPDATED_BY,UPDATED_DATE,STATUS,VERSION,VALIDATE)
Select USER_ID, EMAIL,PASSWORD,PASSWORD_HINT,PWD_CHANGED_DATE,
CREATED_BY,CREATED_DATE,UPDATED_BY,UPDATED_DATE,STATUS,VERSION,VALIDATE From #Sample
END TRY
BEGIN CATCH
Select USER_ID, EMAIL,PASSWORD,PASSWORD_HINT,PWD_CHANGED_DATE,
CREATED_BY,CREATED_DATE,UPDATED_BY,UPDATED_DATE,STATUS,VERSION,VALIDATE From #Sample
END CATCH
END
I used a User-defined Table Type for the Stored Procedure:
-- Create a table data type
CREATE TYPE [dbo].[SampleUserData] As Table
(
--This type has structure similar to the DB table
USER_ID Nvarchar(20) ,
EMAIL Nvarchar(50),
PASSWORD Nvarchar(100),
PASSWORD_HINT Nvarchar(20),
PWD_CHANGED_DATE date,
CREATED_BY Nvarchar(20),
CREATED_DATE date,
UPDATED_BY Nvarchar(20),
UPDATED_DATE date,
STATUS Nvarchar(20),
VERSION Int,
VALIDATE Nvarchar(10)
);
Right now, my Stored Procedure inserts the whole bulk of data at once. When an exception occurs, it returns the whole DataSet (I do not know how to separate the rows).
PS: If there is any other method for the above scenario which is easier, please let me know.
Thanks.
This will do the same as your stored procedure one line at a time:
This was written for SQL Server 2005
BEGIN
--I'm only using your first three columns in this example
DECLARE #USER_ID as Nvarchar(20);
DECLARE #Email as Nvarchar(20);
DECLARE #Password as Nvarchar(20);
DECLARE #SampleCursor as CURSOR;
SET #SampleCursor = CURSOR FOR
SELECT USER_ID, EMAIL, PASSWORD
FROM #Sample;
OPEN #SampleCursor;
--Can't insert directly into table from table variable so save as scalar variable first
FETCH NEXT FROM #SampleCursor INTO #USER_ID, #Email, #Password;
WHILE ##FETCH_STATUS = 0
BEGIN
FETCH NEXT FROM #SampleCursor INTO #USER_ID, #Email, #Password;
BEGIN TRY
--then insert scalar variables into table
INSERT INTO USER (USER_ID, Email, Password) VALUES( #USER_ID, #Email, #Password)
END TRY
BEGIN CATCH
SELECT #USER_ID, #Email, #Password
END CATCH
END
CLOSE #SampleCursor;
DEALLOCATE #SampleCursor;
END
This might work. Just insert your source table one line at a time using TOP(1). The solution below creates a table temporarily so your source table isn't deleted.
--create copy of source table
SELECT * INTO TempTbl FROM Source_Table
--loop through temp table
WHILE EXISTS (SELECT * FROM TempTbl)
BEGIN
--insert first line of temp table into destination table
BEGIN TRY
INSERT INTO [USER] SELECT TOP (1) * FROM TempTbl
END TRY
BEGIN CATCH
SELECT TOP(1) FROM TempTbl
END CATCH
--remove inserted line from temp table
DELETE TOP (1) FROM TempTbl
END
DROP TABLE TempTbl
Update.
This works for me:
CREATE PROCEDURE SOProc
-- Add the parameters for the stored procedure here
#Source_Table_Name sysname = ''
AS
BEGIN
EXEC(
'SELECT * INTO TempTbl FROM ' + #Source_Table_Name)
WHILE EXISTS (SELECT * FROM TempTbl)
BEGIN
BEGIN TRY
INSERT INTO User_Table SELECT TOP (1) * FROM TempTbl
END TRY
BEGIN CATCH
SELECT TOP(1) * FROM TempTbl
END CATCH
DELETE TOP (1) FROM TempTbl
END
DROP TABLE TempTbl
END
GO
Why not use a where clause to validate the data
-- insert valid data
insert into [USER] (USER_ID,EMAIL,PASSWORD,PASSWORD_HINT,PWD_CHANGED_DATE,
CREATED_BY,CREATED_DATE,UPDATED_BY,UPDATED_DATE,STATUS,VERSION,VALIDATE)
select USER_ID, EMAIL,PASSWORD,PASSWORD_HINT,PWD_CHANGED_DATE,
CREATED_BY,CREATED_DATE,UPDATED_BY,UPDATED_DATE,STATUS,VERSION,VALIDATE
from #Sample
where USER_ID is not null
-- select invalid data
select USER_ID, EMAIL,PASSWORD,PASSWORD_HINT,PWD_CHANGED_DATE,
CREATED_BY,CREATED_DATE,UPDATED_BY,UPDATED_DATE,STATUS,VERSION,VALIDATE
from #Sample
where USER_ID is null
An example of a more detailed validation check
select USER_ID, EMAIL,PASSWORD,PASSWORD_HINT,PWD_CHANGED_DATE,
CREATED_BY,CREATED_DATE,UPDATED_BY,UPDATED_DATE,STATUS,VERSION,VALIDATE
from #Sample S
where USER_ID is not null
and EMAIL is not null
and PASSWORD is not null -- etc
-- check record is not duplicate
and not exists (select 1 from [USER] U where U.USER_ID = S.USER_ID)
and isnumeric(USER_ID)

SQL Server IF..ELSE do not show at Windows Application

I have this stored procedure:
exec sp_Defect_B '2013-05-20 00:00:00','2013-05-25 23:59:59'
Which has a IF..ELSE to execute different thing depends on the code given:
alter proc [dbo].[p_Defect_B] (#dtFrom datetime, #dtTo datetime)
as
begin
DECLARE #Total TABLE
(
[No] int, TSampel float
)
-- Total
insert into #Total
select 1 as [No], SUM(H.Total) as TSampel from TrxDBHHDr HH
left join TrxDBHdr H on HH.DBNO=H.DBNO
left join ProductType PT on H.ACd=PT.ACd and PT.GCd=1
where HH.Deleted=0 and HH.DBDate between #dtFrom and #dtTo
DECLARE #Defect TABLE
(
DefectCd varchar(15),Name varchar(50), Defect float
)
-- Defect
insert into #Defect
select D.DefectCd,DB.Name,sum(coalesce(D.Qty,0)) as Defect from TrxDBHHDr HH
left join TrxDBDtl D on HH.DBNO=D.DBNO
left join ProductType PT on D.acd=PT.ACd and PT.GCd=1
left join DefectBK DB on DB.DefectCd=D.DefectCd
where HH.Deleted=0 and HH.DBDate between #dtFrom and #dtTo
group by D.DefectCd,DB.Name
DECLARE #SubTotal TABLE
(
Name varchar(50), Defect float, TSampel float, PDefect float
)
insert into #SubTotal
select D.Name,D.Defect,T.TSampel,D.Defect*100/T.TSampel as PDefect from #Defect D
left join #Total T on T.[No]=1
order by PDefect desc
DECLARE #TotalD TABLE
(
[No] int,Defect float
)
insert into #TotalD
select 1, Sum(D.Defect) as Defect from #Defect D
insert into #SubTotal
select 'Total Defect', D.Defect, T.TSampel, D.Defect*100/T.TSampel as PDefect from #TotalD D
left join #Total T on T.[No]=1
select * from #SubTotal
end
I execute the code in SSMS and it worked perfectly. But when I try to use the code in C# Windows application it doesn't get any value.... How is that possible? Did I miss anything?
Only this stored procedure didn't return table value....
I tried using temp table, table variable, they still didn't return table value...
This is the C# Code:
sql= "exec p_Defect_B '2013-05-20 00:00:00','2013-05-25 23:59:59'";
RunQuery qu_data = new RunQuery();
DataTable data = new DataTable();
data = qu_data.OpenAdoQuery(sql,"IP")
This is part of my program of my connection C# to SQL Server
myCon = new OleDbConnection(strCon);
DataTable myData = new DataTable();
myCon.Open();
OleDbDataAdapter myOleAdapter = new OleDbDataAdapter();
myOleAdapter.SelectCommand = new OleDbCommand(sql,myCon);
myOleAdapter.Fill(myData);
myCon.Close();
All the tables return value in SMSS.
All table variable show result in SMSS.
The result didn't show on C# Windows Application using ADOAdapter.
I tried using Temp Table and Table Variable, didn't work.
I tried not using IF..ELSE, didn't work.
You should really use the SqlConnection then connecting to SQL Server - and you should execute your stored procedure using a standard SqlCommand - don't use the EXEC.... code.
Try this code:
// setup connection and command
using (SqlConnection conn = new SqlConnection(-your-connection-string-here-))
using (SqlCommand cmd = new SqlCommand("dbo.p_Defect_B", conn))
{
// define command as stored procedure
cmd.CommandType = CommandType.StoredProcedure;
// define and set parameter values
cmd.Parameters.Add("#dtFrom", SqlDbType.DateTime).Value = new DateTime(2013, 5, 20);
cmd.Parameters.Add("#dtFrom", SqlDbType.DateTime).Value = new DateTime(2013, 5, 25, 23, 59, 59);
// execute your query
conn.Open();
// get a data reader to read the values from the result set
using (SqlDataReader rdr = cmd.ExecuteReader())
{
// iterate over the result set
while (rdr.Read())
{
// fetch the values - depends on your result set - YOU NEED TO ADAPT THIS!
var value1 = rdr.GetInt(0);
var value2 = rdr.GetString(1);
......
}
rdr.Close();
}
conn.Close();
}

Count Data from Database using stored Procedure w/ inner join [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I'm having a problem counting data w/ inner join.
I want to count how many cottages are available, here are my tables:
here's my code in class getting the cottage number.
public void CheckCottages()
{
con.Close();
SqlCommand comUmbrella = new SqlCommand("CountCottages", con);
comUmbrella.CommandType = CommandType.StoredProcedure;
comUmbrella.Parameters.Add("#CottageType", SqlDbType.NVarChar).Value = "Umbrella";
comUmbrella.Parameters.Add("#ReservedDate", SqlDbType.DateTime).Value = this.ARRIVAL;
con.Open();
comUmbrella.ExecuteNonQuery();
drUmbrella = comUmbrella.ExecuteReader();
if (drUmbrella.Read())
{
this.UMBRELLA = drUmbrella.GetInt32(drUmbrella.GetOrdinal("Rows"));
}
con.Close();
SqlCommand comNativeKubo = new SqlCommand("CountCottages", con);
comNativeKubo.CommandType = CommandType.StoredProcedure;
comNativeKubo.Parameters.Add("#CottageType", SqlDbType.NVarChar).Value = "Native Kubo";
comNativeKubo.Parameters.Add("#ReservedDate", SqlDbType.DateTime).Value = this.ARRIVAL;
con.Open();
comNativeKubo.ExecuteNonQuery();
drKubo = comNativeKubo.ExecuteReader();
if (drKubo.Read())
{
this.NATIVEKUBO = drKubo.GetInt32(drKubo.GetOrdinal("Rows"));
}
con.Close();
SqlCommand comTreeHouse = new SqlCommand("CountCottages", con);
comTreeHouse.CommandType = CommandType.StoredProcedure;
comTreeHouse.Parameters.Add("#CottageType", SqlDbType.NVarChar).Value = "Tree house";
comTreeHouse.Parameters.Add("#ReservedDate", SqlDbType.DateTime).Value = this.ARRIVAL;
con.Open();
comTreeHouse.ExecuteNonQuery();
drTree = comTreeHouse.ExecuteReader();
if (drTree.Read())
{
this.TREEHOUSE = drTree.GetInt32(drTree.GetOrdinal("Rows"));
}
con.Close();
SqlCommand comPavillion = new SqlCommand("CountCottages", con);
comPavillion.CommandType = CommandType.StoredProcedure;
comPavillion.Parameters.Add("#CottageType", SqlDbType.NVarChar).Value = "Pavillion";
comPavillion.Parameters.Add("#ReservedDate", SqlDbType.DateTime).Value = this.ARRIVAL;
con.Open();
comPavillion.ExecuteNonQuery();
drPavillion = comPavillion.ExecuteReader();
if (drPavillion.Read())
{
this.PAVILLION = drPavillion.GetInt32(drPavillion.GetOrdinal("Rows"));
}
}
Here's my stored Procedure:
ALTER PROCEDURE dbo.CountCottages
(
#CottageType nvarchar(50),
#ReservedDate datetime
)
AS
SELECT count(dbo.Cottages.CottageName)
FROM dbo.Cottages INNER JOIN
dbo.ResortTransactions ON dbo.Cottages.CottageID = dbo.ResortTransactions.CottageID
where dbo.Cottages.CottageType=#CottageType and dbo.ResortTransactions.Status != 'Cancelled' and dbo.ResortTransactions.ReservedDate != #ReservedDate
RETURN
What's wrong to my code? I hope someone can help me :)
Thanks in advance!
Since there's not much information about how your data is used, here's a guess. I'm assuming you want a count of cottages where there is a transaction where 1) the status is not cancelled and 2) the date is equal to the reservation date. If so here's the query:
SELECT count(dbo.Cottages.CottageName)
FROM dbo.Cottages
WERE CottageType=#CottageType
AND CottageID NOT IN
(SELECT CottageID FROM dbo.ResortTransactions
WHERE Status != 'Cancelled'
AND ReservedDate = #ReservedDate)
Also you are executing the sproc twice - once using ExecuteNonQuery and once using ExecuteReader You should either return a value and use ExecuteNonQuery, creating a parameter to store the return value, or use ExecuteScalar to quickly pull the first result from the dataset.
I would suggest reading up more on basic SQL and how to execute queries with .NET.
You are not returning the COUNT.
Declare a variable, initialize it with the result and return it from the procedure:
ALTER PROCEDURE dbo.CountCottages
(
#CottageType nvarchar(50),
#ReservedDate datetime
)
AS
BEGIN
DECLARE #NumCottages int
SELECT #NumCottages = count(dbo.Cottages.CottageName)
FROM dbo.Cottages INNER JOIN
dbo.ResortTransactions ON dbo.Cottages.CottageID = dbo.ResortTransactions.CottageID
where dbo.Cottages.CottageType=#CottageType and dbo.ResortTransactions.Status != 'Cancelled' and dbo.ResortTransactions.ReservedDate != #ReservedDate
RETURN #NumCottages
END
Then use SqlCommand.ExecuteScalar instead of ExecuteNonQuery to get the value.
Cmd.ExeceuteNonQuery() is normally used to execute a procedure without expecting a result back.
But here you are looking for a scalar value.So Change it to cmd.ExecuteScalar().Also return the count back from the procedure.
I'll make a few assumptions - just a small tip whilst playing with this I would create a "scratch pad" in a SQL query and use table variables to test with as you can see below:
DECLARE #Cottages AS TABLE
(
Cottage_PK INT IDENTITY(1, 1) ,
CottageName VARCHAR(100) ,
CottageType VARCHAR(100)
)
DECLARE #Reservations AS TABLE
(
Reservation_PK INT IDENTITY(1, 1) ,
Cottage_FK INT ,
CheckinDate DATETIME ,
DepatureDate DATETIME ,
IsCanceled BIT
)
DECLARE #DateToCheck AS DATETIME ,
#CottageType AS VARCHAR(100)
SET #DateToCheck = '2012-09-15'
SET #CottageType = 'Some Type'
INSERT INTO #Cottages
( CottageName, CottageType )
VALUES ( 'CottageA', 'Some Type' )
INSERT INTO #Reservations
( Cottage_FK ,
CheckinDate ,
DepatureDate ,
[Status]
)
VALUES ( 1 , -- Cottage_FK - int
'2012-09-16' , -- CheckinDate - datetime
'2012-09-24' , -- DepatureDate - datetime
''
)
Now I took the assumption that if you want to check cottages availible on a date you would need to check in accordance to the checkin date and the depature date which results in using a between statement.
SELECT COUNT(c.CottageName) AS 'Cottages availible'
FROM #Cottages c
INNER JOIN #Reservations r ON c.Cottage_PK = r.Cottage_FK
WHERE NOT #DateToCheck BETWEEN r.CheckinDate
AND r.DepatureDate
AND c.[status] != 'Cancelled'
AND c.CottageType = #CottageType
Use this for testing - I passed a date within the range it it returned 0 and out of the range and it returned 1. Once your happy move this to your stored procedure.
CREATE PROCEDURE dbo.CountCottages
#DateToCheck DATETIME ,
#CottageType VARCHAR(100)
AS
SELECT COUNT(c.CottageName) AS 'Cottages availible'
FROM Cottages c
INNER JOIN ResortTransactions r ON c.Cottage_PK = r.Cottage_FK
WHERE NOT #DateToCheck BETWEEN r.CheckinDate
AND r.DepatureDate
AND c.[status] != 'Cancelled'
AND c.CottageType = #CottageType

Is it possible to query records obtained from extended stored procedures from TSQL in C#?

So this is the code I have tried, in C#, which failed to give me the result I needed.
SqlCommand comm = new SqlCommand("exec sys.xp_readerrorlog 0,1,'','',#StartDate,#EndDate,N'Desc'");, conn);
comm.Parameters.AddWithValue("#StartDate", "");
comm.Parameters.AddWithValue("#EndDate", "");
SqlDataReader dr = comm.ExecuteReader();
while (dr.Read())
{
Console.WriteLine(dr.GetString(0));
}
Basically, I need to extract data from these logs (which gets pulled from the SQL Server through this stored procedure), and it seems that When I use a dataReader, there are no records, and if I use a dataset with data adapter, there are also no tables/records in the dataset. This information is critical for me to query.
Is there a way that I can still query the SQL Server error logs without having to resort to stored procedures?
ANOTHER UPDATE:
The parameters for this extended stored procedures are:
Value of error log file you want to read: 0 = current, 1 = Archive, 2 = etc...
Log file type: 1 or NULL = error log, 2 = SQL Agent log
Search string 1: String one you want to search for
Search string 2: String two you want to search for to further refine
the results
Search from start time
Search to end time
Sort order for results: N'asc' = ascending, N'desc' = descending
Another method I tried
SqlCommand comm = new SqlCommand(#"exec sys.xp_readerrorlog 0,1,'','',null,null,N'Desc'", conn);
SqlDataAdapter da = new SqlDataAdapter(comm);
DataSet ds = new DataSet();
Console.WriteLine(ds.Tables.Count); //0 returned: no data in dataset
If i was allowed to use stored procedures to query the data, I could have used this following extract, but it would have been deployed too much and be a pain to maintain and decommission
IF (EXISTS( SELECT * FROM sys.procedures where name = 'writelogs' ))
BEGIN
DROP PROCEDURE Writelogs;
END
GO
CREATE PROCEDURE WriteLogs #Servername varchar(40),#InstanceName varchar(40),#Pattern varchar(max),#ParamBeginDate varchar(40), #ParamEndDate varchar(40) AS
BEGIN
DECLARE #BeginDate DateTime
DECLARE #EndDate DateTime
DECLARE #NextQueryID int
--First we have to convert the timestamps EndDate and BeginDate to something usable
IF (#ParamBeginDate = 'Beginning')
BEGIN
SET #BeginDate = null; --null will cause sys.xp_readerrorlog to read from beginning
END
ELSE IF (#ParamBeginDate = 'Last')
BEGIN
SELECT TOP 1 #BeginDate = L.TimeLogged FROM LogTable L ORDER BY L.TimeLogged Desc
END
ELSE
BEGIN
BEGIN TRY
SET #BeginDate = CAST(#ParamBeginDate AS DATETIME);
END TRY
BEGIN CATCH
SET #BeginDate = null;
END CATCH
END
IF (#ParamEndDate = 'Now')
BEGIN
SET #EndDate = GETDATE(); --null will cause sys.xp_readerrorlog to read till now
END
ELSE
BEGIN
BEGIN TRY
SET #EndDate = CAST(#ParamEndDate AS DATETIME);
END TRY
BEGIN CATCH
SET #EndDate = GETDATE();
END CATCH
END
--Temporary Table to store the logs in the format it is originally written in
CREATE TABLE TMP
(LogDate DateTime2
,Processinfo varchar(40)
,[Text] varchar(max))
--truncate the milliseconds (else ALL records will be retrieved)
SET #EndDate= dateadd(millisecond, -datepart(millisecond, #EndDate),#EndDate);
SET #BeginDate= dateadd(millisecond, -datepart(millisecond, #BeginDate),#BeginDate);
INSERT INTO TMP exec sys.xp_readerrorlog 0,1,'','',#BeginDate,#EndDate,N'DESC';
SELECT TOP 1 L.TimeLogged FROM LogTable L ORDER BY L.Timelogged desc
INSERT INTO LogTable
SELECT #Servername,#InstanceName,T.[text],T.LogDate,GETDATE(),0,0,null,#NextQueryID FROM TMP t WHERE PATINDEX(#Pattern,t.[Text]) > 0;
DROP TABLE TMP;
END
You can't use AddWithValue for the dates.
If the dates are blank, then you need to pass null as the value, not an empty string. Those have completely different meanings.
To test, open Management Studio and execute the following:
exec sys.xp_readerrorlog 0,1, '', '', '', ''
That will have zero results. However if you do this:
exec sys.xp_readerrorlog 0,1, '', '', null, null
You will get back a lot of records.
BTW, your update is still wrong. The dataset code you have will never do anything. Change it to:
SqlCommand comm = new SqlCommand(#"exec sys.xp_readerrorlog 0,1,'','',null,null,N'Desc'", conn);
SqlDataAdapter da = new SqlDataAdapter(comm);
DataSet ds = new DataSet();
da.Fill(ds, "sometablename");
Console.WriteLine(ds.Tables.Count); //0 returned: no data in dataset
Note the fill command...

Categories