I am trying to fill a DataTable reading a view using SqliteDataReader. The following code works when I am reading a Table (not a view)
private DataTable ReadDataTable(SqliteCommand command)
{
DataTable result = new();
using (var connection = Connection)
{
connection.Open();
SqliteDataReader reader = command.ExecuteReader();
result.Load(reader);
}
return result;
}
However, when the table in question is a view, containing multiple rows, the resulting table only contains one row. To test I tried the following function, running the same command
private int ReadDataTableTest(SqliteCommand command)
{
int result = 0;
using (var connection = Connection)
{
connection.Open();
SqliteDataReader reader = command.ExecuteReader();
while(reader.Read())
result++;
}
return result;
}
This returned 6, the correct answer. Also, querying the table directly in SqliteStudio gives the right answer. The top function seems only to insert the last row of the reader in the DataTable. What is going on here?
Btw, I don't know for sure that the issue is that the table is a view, but I have a similar issue with many other views, and the "view/table" thing seems to be the common denominator.
I am using Windows, coding in .net6. using the following imports
using Microsoft.Data.Sqlite;
using System.Data;
EDIT
I am creating the command like this
private SqliteCommand CreateCommand(string tableName, DateTime reportDate)
{
var command = Connection.CreateCommand();
command.CommandText = #$"SELECT * FROM {tableName} WHERE ReportDate = $reportDate";
command.Parameters.AddWithValue("$reportDate", reportDate.ToSqliteDate());
return command;
}
And calling the code like this
var reportDate = new DateTime(2022, 7, 31);
var table = ReadDataTable(CreateCommand("MyTable", reportDate));
I am not doing anything to the table after the call.
EDIT 2
The following query generates the view
SELECT [of].ReportDate,
[of].Entity,
SUM(CASE WHEN [of].Item IN ('Equity') THEN [of].Value / fx.FxRate ELSE 0 END) AS EquityLocal,
SUM(CASE WHEN [of].Item IN ('AdjIFRS') THEN [of].Value / fx.FxRate ELSE 0 END) AS AdjIFRSLocal,
SUM(CASE WHEN [of].Item IN ('AdjIFRSGroup') THEN [of].Value / fx.FxRate ELSE 0 END) AS AdjIFRSGroup,
SUM(CASE WHEN Entity != 'Holding' AND
[of].Item IN ('Equity', 'AdjIFRS', 'AdjIFRSGroup') THEN -[of].Value / fx.FxRate ELSE 0 END) AS Elimination,
SUM(CASE WHEN Entity = 'Holding' AND
[of].Item IN ('Equity', 'AdjIFRS', 'AdjIFRSGroup') THEN [of].Value / fx.FxRate ELSE 0 END) AS EquityIFRS,
'EUR' AS ReportCurrency
FROM InputOwnFunds AS [of]
JOIN InputEurFxRates AS fx
ON [of].ReportDate = fx.ReportDate AND
[of].ReportCurrency = fx.ReportCurrency
WHERE of.Item in ('Equity', 'AdjIFRS', 'AdjIFRSGroup')
GROUP BY [of].ReportDate,
[of].Entity
UNION
SELECT [of].ReportDate,
'NLP Group' as Entity,
SUM(CASE WHEN [of].Item IN ('Equity') THEN [of].Value / fx.FxRate ELSE 0 END) AS EquityLocal,
SUM(CASE WHEN [of].Item IN ('AdjIFRS') THEN [of].Value / fx.FxRate ELSE 0 END) AS AdjIFRSLocal,
SUM(CASE WHEN [of].Item IN ('AdjIFRSGroup') THEN [of].Value / fx.FxRate ELSE 0 END) AS AdjIFRSGroup,
SUM(CASE WHEN Entity != 'Holding' AND
[of].Item IN ('Equity', 'AdjIFRS', 'AdjIFRSGroup') THEN -[of].Value / fx.FxRate ELSE 0 END) AS Elimination,
SUM(CASE WHEN Entity = 'Holding' AND
[of].Item IN ('Equity', 'AdjIFRS', 'AdjIFRSGroup') THEN [of].Value / fx.FxRate ELSE 0 END) AS EquityIFRS,
'EUR' AS ReportCurrency
FROM InputOwnFunds AS [of]
JOIN InputEurFxRates AS fx
ON [of].ReportDate = fx.ReportDate AND
[of].ReportCurrency = fx.ReportCurrency
WHERE of.Item in ('Equity', 'AdjIFRS', 'AdjIFRSGroup')
GROUP BY [of].ReportDate
Related
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 7 years ago.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Improve this question
I am fetching quarterly records from sql server. The records are like total debits and credits in each quarter of year. In my sql query I have made the quarters and the year is dynamic as you can see in the code.
public List<QuarterlyExpenseList> GetExpenseDataQuarterly(string Id, string Year)
{
string SQL = "select aspnetusers.username, SUM(case when Expense.Type='credit' and (Expense.Date>='#year-01-01' and Expense.Date<='#year-03-31') then Expense.Amount else 0 end) as QuarterOneCredits,";
SQL += " SUM(case when Expense.Type='credit' and (Expense.Date>='#year-04-01' and Expense.Date<='#year-06-30') then Expense.Amount else 0 end) as QuarterTwoCredits,";
SQL += " SUM(case when Expense.Type='credit' and (Expense.Date>='#year-07-01' and Expense.Date<='#year-09-30') then Expense.Amount else 0 end) as QuarterThreeCredits,";
SQL += " SUM(case when Expense.Type='credit' and (Expense.Date>='#year-10-01' and Expense.Date<='#year-12-31') then Expense.Amount else 0 end) as QuarterFourCredits,";
SQL += " SUM(case when Expense.Type='debit' and (Expense.Date>='#year-01-01' and Expense.Date<='#year-03-31') then Expense.Amount else 0 end) as QuarterOneDebits,";
SQL += " SUM(case when Expense.Type='debit' and (Expense.Date>='#year-04-01' and Expense.Date<='#year-06-30') then Expense.Amount else 0 end) as QuarterTwoDebits,";
SQL += " SUM(case when Expense.Type='debit' and (Expense.Date>='#year-07-01' and Expense.Date<='#year-09-30') then Expense.Amount else 0 end) as QuarterThreeDebits,";
SQL += " SUM(case when Expense.Type='debit' and (Expense.Date>='#year-10-01' and Expense.Date<='#year-12-31') then Expense.Amount else 0 end) as QuarterFourDebits";
SQL += " from Expense inner join AspNetUsers on AspNetUsers.Id=Expense.MadeBy";
if (Id == null)
{
SQL += " group by aspnetusers.username";
}
else
{
SQL += " where Expense.MadeBy=#id group by AspNetUsers.UserName group by aspnetusers.username";
}
using (IDbConnection cn=Connection)
{
cn.Open();
List<QuarterlyExpenseList> objList = cn.Query<QuarterlyExpenseList>(SQL, new { year = Year, id = Id }).ToList();
return objList;
}
}
here I am getting an exception of Conversion failed when converting date and/or time from character string. Can somebody tell me what does it mean and how can I get rid of it
I removed the dynamic year "#year" outside character string as it is a dynamic value. When written like '#year-04-01' SQL was treating "#year" as a character string and not as a dynamic value.
Use the following code:
public List<QuarterlyExpenseList> GetExpenseDataQuarterly(string Id, string Year)
{
string SQL = "select aspnetusers.username, SUM(case when Expense.Type='credit' and (Expense.Date>=#year+'-01-01' and Expense.Date<=#year+'-03-31') then Expense.Amount else 0 end) as QuarterOneCredits,";
SQL += " SUM(case when Expense.Type='credit' and (Expense.Date>=#year+'-04-01' and Expense.Date<=#year+'-06-30') then Expense.Amount else 0 end) as QuarterTwoCredits,";
SQL += " SUM(case when Expense.Type='credit' and (Expense.Date>=#year+'-07-01' and Expense.Date<=#year+'-09-30') then Expense.Amount else 0 end) as QuarterThreeCredits,";
SQL += " SUM(case when Expense.Type='credit' and (Expense.Date>=#year+'-10-01' and Expense.Date<=#year+'-12-31') then Expense.Amount else 0 end) as QuarterFourCredits,";
SQL += " SUM(case when Expense.Type='debit' and (Expense.Date>=#year+'-01-01' and Expense.Date<=#year+'-03-31') then Expense.Amount else 0 end) as QuarterOneDebits,";
SQL += " SUM(case when Expense.Type='debit' and (Expense.Date>=#year+'-04-01' and Expense.Date<=#year+'-06-30') then Expense.Amount else 0 end) as QuarterTwoDebits,";
SQL += " SUM(case when Expense.Type='debit' and (Expense.Date>=#year+'-07-01' and Expense.Date<=#year+'-09-30') then Expense.Amount else 0 end) as QuarterThreeDebits,";
SQL += " SUM(case when Expense.Type='debit' and (Expense.Date>=#year+'-10-01' and Expense.Date<=#year+'-12-31') then Expense.Amount else 0 end) as QuarterFourDebits";
SQL += " from Expense inner join AspNetUsers on AspNetUsers.Id=Expense.MadeBy";
if (Id == null)
{
SQL += " group by aspnetusers.username";
}
else
{
SQL += " where Expense.MadeBy=#id group by AspNetUsers.UserName group by aspnetusers.username";
}
using (IDbConnection cn=Connection)
{
cn.Open();
List<QuarterlyExpenseList> objList = cn.Query<QuarterlyExpenseList>(SQL, new { year = Year, id = Id }).ToList();
return objList;
}
}
I'm using c# winform sql server
In my database I try to manage the employee vacations in my small company so I was created two tables
first table called tblMember
idMember (PK, int, not null)
memberName (varchar(50), null)
that table related in one to many relationship to
second table called tblVacations
idVacation (PK, int, not null)
vacationStart (date, null)
vacationEnd (date, null)
idMember_L(FK, int, null)
then I created a form with two datagridview the first called dg_member populate its data (names from tblMember) throw a stored procedure
the second datagridview dgVacation populate the related data
now I want to colored with red the name in dg_member who absent today ( today is fall between vacationStart and vacationEnd ) and if the member is coming today ( today equal vacationEnd ) the name turn to green
i tried the code :
private void dgMember_Grade_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
foreach (DataGridViewRow Myrow in dgMember_Grade.Rows)
{
var cvStart = dgVacation.Rows[0].Cells[1].Value;
var cvEnd = dgVacation.Rows[0].Cells[2].Value;
if (cvStart == null || cvStart == DBNull.Value)
continue;
DateTime startDate = Convert.ToDateTime(cvStart);
DateTime endDate = Convert.ToDateTime(cvEnd);
if (startDate < DateTime.Now && endDate > DateTime.Now)
{
Myrow.DefaultCellStyle.BackColor = Color.Red;
}
else if (endDate == DateTime.Now)
{
Myrow.DefaultCellStyle.BackColor = Color.Green;
}
}
}
but it gives me an error
Index was out of range. Must be non-negative and less than the size of the collection.
thank you
declare #tmw Date = DATEADD(day, 1,getdate())
select
m.MemberName
, case when t.idMember_L is null then 'False' else 'True' end as OnHoliday
, case when (select count (tm.idMember_L) from tblVacations tm where
m.idMember = tm.idMember_L and
t.vacationStart <= #tmw and t.vacationEnd >= #tmw ) > 0
then 'False' else 'True' end as OnHolidayTomorrow
from tblMember m
left outer join tblVacations t
on m.idMember = t.idMember_L and
t.vacationStart <= getdate() and t.vacationEnd >= getdate()
So first here is my C# code and then comes the stored procedure.
public DataTable GetCourseHighPass(String tmpCourse)
{
command.Connection = OpenConnection();
try
{
command.CommandText = "exec GetCourseCompletions #tmpCourse = '" + tmpCourse + "'";
SqlDataAdapter dataAdapter = new SqlDataAdapter(command);
dataAdapter.Fill(dataTable);
return dataTable;
}
catch (Exception)
{
throw new Exception("There are no VG's for this course.");
}
finally
{
command.Connection.Close();
}
}
And here is my stored procedure.
create procedure GetCourseCompletions
#tmpCourse nvarchar(30)
as
select (count(pnr) * 100 / (select count(pnr)
from HasStudied
where courseCode = #tmpCourse
and count(pnr) =)) as VGPrecentage
from HasStudied
where grade >= 5
and courseCode = #tmpCourse
go
The problem is that if there are no students with a high pass I will get a divide by zero exception. Looking for suggestions on how to catch this exception so the program does not crash or even better to re-write the stored procedure so it does not get an exception in the first place.
Thank you for your assistance!
Do what Eric said:
DECLARE #count int
Set #count = (select count(pnr) from HasStudied where courseCode = #tmpCourse and count(pnr) =...)
IF #count = 0
BEGIN
SELECT 0 as VGPrecentage
END
ELSE
BEGIN
select (count(pnr)*100 / #count) as VGPrecentage from HasStudied where grade >= 5 and courseCode = #tmpCourse
END
I suggest you to use this kind of query instead of yours that will handle NULL values and Zero values:
SELECT
CASE WHEN part * total <> 0 THEN part * 100 / total ELSE 0 END
FROM (
SELECT SUM(CASE WHEN grade > 5 THEN 1.00 ELSE 0.00 END) As part, SUM(1.00) as total
FROM HasStudied
WHERE courseCode = #tmpCourse) t
My sql table contains date of birth of many people.dates are in mm/dd/yyyy format. I want select the persons details whose birth day in next 30days. And i use the following query for that,
SELECT Mem_FirstNA, Mem_LastNA, Mem_DOB FROM MemberDetails WHERE
ltrim(str(year(GETDATE()))) + -' + ltrim(str(month(Mem_DOB))) + '-' +
ltrim(str(day(Mem_DOB))) >= getdate() - 1 AND
ltrim(str(year(GETDATE()))) + '-' + ltrim(str(month(Mem_DOB))) + '-' +
ltrim(str(day(Mem_DOB))) <= getdate() + 30
And full code is
public List<MemberData> GetThisMonthBirthday()
{
List<MemberData> MD = new List<MemberData>();
using (SqlConnection con = new SqlConnection(Config.ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("SELECT Mem_FirstNA, Mem_LastNA, Mem_DOB FROM MemberDetails WHERE ltrim(str(year(GETDATE()))) + '-' + ltrim(str(month(Mem_DOB))) + '-' + ltrim(str(day(Mem_DOB))) >= getdate() - 1 AND ltrim(str(year(GETDATE()))) + '-' + ltrim(str(month(Mem_DOB))) + '-' + ltrim(str(day(Mem_DOB))) <= getdate() + 30", con))
{
try
{
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
MemberData mb = new MemberData();
mb.Mem_NA = (string)reader["Mem_FirstNA"];
mb.Mem_LastNA =(string)reader["Mem_LastNA"];
mb.Mem_DOB = (Convert.ToDateTime(reader["Mem_DOB"]));
MD.Add(mb);
}
}
catch (Exception e) { throw e; }
finally { if (con.State == System.Data.ConnectionState.Open) con.Close(); }
return MD;
}
}
The problem is that this check only till December 31, if the persons birthday in 01/01/1987 , the query is not selected that details. Please help me to solve this problem. Thank you
There are lots of ways to do this, you need conditional logic depending on whether or not you are within 30 days of the end of the year. If you're using SQL Server, I'd wrap the logic in a function to make it more readable, e.g.:
CREATE FUNCTION [dbo].[IsBirthdayInRange]
(
#Birthday DATETIME,
#StartDate DATETIME,
#EndDate DATETIME
)
RETURNS BIT
AS
BEGIN
DECLARE #StartMonthDay INT
DECLARE #EndMonthDay INT
DECLARE #BirthdayMonthDay INT
SET #StartMonthDay = MONTH(#StartDate) * 100 + DAY(#StartDate)
SET #EndMonthDay = MONTH(#EndDate) * 100 + DAY(#EndDate)
SET #BirthdayMonthDay = MONTH(#Birthday) * 100 + DAY(#Birthday)
IF YEAR(#StartDate) <> YEAR(#EndDate)
BEGIN
IF #BirthdayMonthDay >= #StartMonthDay OR #BirthdayMonthDay <= #EndMonthDay
BEGIN
RETURN 1
END
END
ELSE
BEGIN
IF #BirthdayMonthDay >= #StartMonthDay AND #BirthdayMonthDay <= #EndMonthDay
BEGIN
RETURN 1
END
END
RETURN 0
END
You can then use it as:
...
WHERE IsBirthdayInRange(Mem_DOB, GETDATE(), GETDATE() + 30)
I have a stored procedure with the following code, it works fine in sql server. I need to use the returned rows to work with the stacked column chart. I don't know how to receive these rows, though I have tried to do so with code given after the stored procedure code. I would really appreciate if anyone could find out where I am doing something wrong. Thank you :)
Stored Procedure Code:
ALTER PROCEDURE [dbo].[weekly]
#id_beleg int /* CONTAINS THE ID OF THE MACHINE FOR WHICH THE NUMBER OF ORDERS IS REQUIRED*/
AS
BEGIN
DECLARE #montag DATETIME
DECLARE #weekend DATETIME
SET #montag = DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0)
/* SET #MONTAG VARIABLE TO THE DATE ON MONDAY OF THE CURRENT WEEK*/
SET #weekend = dateadd(day, 6, #montag)
/* SET #WEEKEND VARIABLE TO THE DATE ON SUNDAY OF THE CURRENT WEEK*/
/* CONTAINS ALL RECORDS OF one PROCESS FOR THE CURRENT WEEK*/
CREATE TABLE #WeeklySieben
(
Tag datetime,
Aufträge_anzahl int,
Anlage varchar(30)
);
INSERT INTO #WeeklySieben (Tag, Aufträge_anzahl, Anlage)
SELECT *
FROM
dbo.Sieben
WHERE
Tag BETWEEN #montag AND GETDATE()
ORDER BY Tag
DECLARE #tempdate datetime
/* CONTAINS ONLY THE UNIQUE MACHINE NAMES*/
CREATE TABLE #Anlage_Sieben
(
Anl varchar(30)
)
/* CONTAINS DATE FOR ALL DAYS OF THE CURRENT WEEK*/
CREATE TABLE #alldays
(
days datetime
)
INSERT INTO #Anlage_Sieben (Anl)
SELECT KURZTEXT as Anl
FROM dbo.tblBELEGUNGSEINHEIT
WHERE ID in (SELECT ID_BELEGUNGSEINHEIT FROM dbo.tblPROZESS_BELEGUNGSEINHEIT WHERE ID_PROZESS = 5)
/* SELECT MACHINE ID WHERE PROCESS IS number 5*/
WHILE #montag <= #weekend
BEGIN
INSERT INTO #alldays (days)
SELECT days = #montag
SET #tempdate= #montag
SET #montag = dateadd(day, 1,#tempdate)
END
/* MACHINE NAME * WEEKDAYS DATE*/
CREATE TABLE #weekdays
(
daydate datetime,
Anlage varchar(30)
)
INSERT INTO #weekdays (daydate, Anlage)
SELECT d.days as daydate
, a.Anl as Anlage
FROM #Anlage_Sieben a
CROSS JOIN #alldays d
/* SELECT NUMBER OF ORDERS ON A PARTICULAR MACHINE FOR ALL WEEK DAYS*/
Select case
when Aufträge_anzahl is null then '0'
else Aufträge_anzahl
end
from #WeeklySieben W right join #weekdays wd on W.Anlage = wd.Anlage and W.Tag = wd.daydate
where wd.Anlage in (select KURZTEXT from dbo.tblBELEGUNGSEINHEIT where ID = #id_beleg )
END
C# Code:
try
{
int a;
string sql = "weekly";
SqlDataAdapter dp = new SqlDataAdapter();
SqlCommand c = null;
SqlDataReader r = null;
DataSet ds = new DataSet();
DataTable dt = new DataTable();
//For creating 'raum' number of stacked column bars
for (int i = 0; i < raum; i++)
{
c = new SqlCommand(sql, conn);
c.CommandType = CommandType.StoredProcedure;
c.Parameters.Add("#raumn", SqlDbType.Int).Value= (int)dblOrders[i];
r = c.ExecuteReader();
dp.SelectCommand = c;
dp.Fill(ds, "Aufträge_anzahl");
dt = ds.Tables["Aufträge_anzahl"];
//For adding points to a stacked column bar
for (int j = 0; j < dt.Rows.Count; j++)
{
a = Convert.ToInt32(dt.Rows[j]);
Chart1.Series[seriesArray[j]].Points.AddY(a);
}
Chart1.DataBind();
dtSr.Clear();
}
}
catch (SqlException ex)
{
Console.WriteLine("SQL Error" + ex.Message.ToString());
}
dblorders is the double array which holds the IDs for different machines, raum is the number of total machines. The code generates no error, but it does not retrieve back the data in the chart.