Join query results in distinct yet duplicate data in the gridview - c#

I wanted to retrieve the name of the employee from one table and the details of their leave application from another table. The condition that differentiates the employee from his reporting boss is the manager_ID column. The employee_ID is fed as value of manager_ID column for each user. The director has null in this field. Now I have populated this data in a gridview using the below query.
SqlConnection conn = new SqlConnection(connectionstring);
SqlCommand cmd = new SqlCommand("select distinct Employee.emp_name,Leave.leave_ID,Leave.leave_type,Leave.reason,Leave.el_start_date,Leave.el_end_date,Leave.total_days,Leave.status from Employee CROSS JOIN Leave where Employee.manager_ID='" + lbl_empid.Text + "' AND Leave.status='" + lbl_status.Text + "'", conn);
cmd.CommandType = CommandType.Text;
using (conn)
{
conn.Open();
rdr = cmd.ExecuteReader();
while (rdr.Read())
{
dr = dt.NewRow();
dr["Leave No."] = rdr["leave_ID"].ToString();
dr["Requested By"] = rdr["emp_name"].ToString();
dr["Type of Leave"] = rdr["leave_type"].ToString();
dr["Reason"] = rdr["reason"].ToString();
dr["Starting"] = rdr["el_start_date"].ToString();
dr["Ending"] = rdr["el_end_date"].ToString();
dr["No. of Days"] = rdr["total_days"].ToString();
dr["Status"] = rdr["status"].ToString();
dt.Rows.Add(dr);
dt.AcceptChanges();
}
gv_pending_requests.DataSource = dt;
gv_pending_requests.DataBind();
conn.Close();
}
On debugging, the gridview gets populated without an error. It shows the employees managed by the logged in manager, all right. Only those employees' rows are retrieved and displayed that were required to be. But the data is duplicated in a strange manner. The same row is repeated with a replaced name in the output. I have made a crude imitation of the output I get in my gridview, as I am not allowed to post images. The output shows the data for all the users that have the same manager, by repeating it. While in reality I made these requests from the account of Avneesh only, not ravi:
Lv. No. Employee Name LeaveType Reason Starting Date
2 Avneesh Earned, Casual Personal 17/11/2014
2 Ravi Earned, Casual Personal 17/11/2014
5 Avneesh Earned, Half-Pay Conference 17/11/2014
5 Ravi Earned, Half-Pay Conference 17/11/2014
Please point out what I am doing wrong in the query. I have tried using a self join in a subquery, but it shows the error:- {"System.Data.SqlClient.SqlException (0x80131904): Incorrect syntax near the keyword 'where'"}. The query is:
SqlCommand cmd = new SqlCommand("select distinct Employee.emp_name,Leave.leave_ID,Leave.leave_type,Leave.reason,Leave.el_start_date,Leave.el_end_date,Leave.total_days,Leave.status from Employee CROSS JOIN Leave where Employee.manager_ID=(select e.emp_ID,m.emp_ID from Employee e INNER JOIN Employee m where e.mgr_ID=m.emp_ID) AND Leave.status='" + lbl_status.Text + "'", conn);
Now, how do i solve this duplication? Please help.
I am using Visual studio 2013 and sql server 2014.
Edit: Here are the two tables concerned with this query.
CREATE TABLE [dbo].[Employee](
[emp_ID] [numeric](18, 0) IDENTITY(1,1) NOT NULL,
[username] [nvarchar](50) NOT NULL,
[emp_name] [nvarchar](max) NOT NULL,
[password] [nvarchar](max) NOT NULL,
[pay_roll_num] [nvarchar](max) NOT NULL,
[designation] [nvarchar](max) NOT NULL,
[leaves_taken] [nvarchar](max) NOT NULL,
[primary_address] [nvarchar](max) NOT NULL,
[primary_phone] [nvarchar](max) NOT NULL,
[email_ID] [nvarchar](max) NOT NULL,
[manager_ID] [nvarchar](max) NOT NULL,
CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED ( [username] 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 TABLE [dbo].[Leave](
[leave_ID] [numeric](18, 0) IDENTITY(1,1) NOT NULL,
[username] [nvarchar](50) NOT NULL,
[reason] [nvarchar](max) NOT NULL,
[addrs_onLeave] [nvarchar](max) NOT NULL,
[phone_onLeave] [nvarchar](max) NOT NULL,
[alternate_email] [nvarchar](max) NULL,
[leave_type] [nvarchar](max) NOT NULL,
[earned_leave] [nvarchar](max) NULL,
[el_start_date] [nvarchar](max) NULL,
[el_end_date] [nvarchar](max) NULL,
[halfpay_leave] [nvarchar](max) NULL,
[hl_start_date] [nvarchar](max) NULL,
[hl_end_date] [nvarchar](max) NULL,
[commuted_leave] [nvarchar](max) NULL,
[com_startdate] [nvarchar](max) NULL,
[com_end_date] [nvarchar](max) NULL,
[casual_leave] [nvarchar](max) NULL,
[cl_start_date] [nvarchar](max) NULL,
[cl_end_date] [nvarchar](max) NULL,
[rh_leave] [nvarchar](max) NULL,
[rh_start_date] [nvarchar](max) NULL,
[rh_end_date] [nvarchar](max) NULL,
[total_days] [nvarchar](max) NOT NULL,
[status] [nvarchar](max) NOT NULL,
[leave_apply_date] [nvarchar](max) NOT NULL,
CONSTRAINT [PK_Leave] PRIMARY KEY CLUSTERED ( [leave_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]

I agree the CROSS JOIN is the issue.
It is rare to need to CROSS JOIN to a table or query set when that table or query set has multiple rows, thereby creating a cartesian product. On the other hand, I CROSS JOIN to a table or query that has a SINGLE row in it often, but doing so does not increase the number of rows in the result set, and thereby does not duplicate rows.
A good example to conceptualize when to use a CROSS JOIN to a multiple row table or set, is a batch process that needs to post debits and credits (double entry bookkeeping). You can join to a query that contains two rows, one containing 'DEBIT', the other 'CREDIT', and doing so has just doubled all rows in the batch. One half gets posted as a DEBIT, the other half as a CREDIT.

Solved it! Thank you all for suggesting to get rid of the cross join.
Here is the right query, in case anyone else might need it.
SqlCommand cmd = new SqlCommand("select distinct leave_ID,username,leave_type,reason,
el_start_date,el_end_date,total_days,status from Leave where username IN
(select username from Employee where manager_ID='" + lbl_empid.Text + "')
AND Leave.status='" + lbl_deny.Text + "'", conn);

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.

How to display image in picturebox from datagrid?

I am working with Windows Form Application and I have SQL Database with table members and the columns: id, fname, lname, gender, telephone, created, email and picture (the pictures are saved . I am using bound DataGrid with all the columns except the id column. I want the picturebox to show the image from the selected row, I tried everything that I found online but nothing.
This is the table query:
CREATE TABLE [dbo].[members](
[id] [int] IDENTITY(1,1) NOT NULL,
[fname] [varchar](50) NOT NULL,
[lname] [varchar](50) NOT NULL,
[gender] [varchar](10) NOT NULL,
[telephone] [varchar](20) NOT NULL,
[created] [date] NULL,
[picture] [image] NULL,
[email] [varchar](50) NULL,
CONSTRAINT [PK__members__3213E83F00551192] PRIMARY KEY CLUSTERED
And this is the code for showing the columns:
DataGridViewRow row = dataGridView1.Rows[e.RowIndex];
nameText.Text = dataGridView1.CurrentRow.Cells[0].Value.ToString();
lnameText.Text = dataGridView1.CurrentRow.Cells[1].Value.ToString();
genderText.Text = dataGridView1.CurrentRow.Cells[2].Value.ToString();
telephoneText.Text = dataGridView1.CurrentRow.Cells[3].Value.ToString();
datecreaText.Text = dataGridView1.CurrentRow.Cells[4].Value.ToString();
emailText.Text = dataGridView1.CurrentRow.Cells[5].Value.ToString();
var data = (Byte[])(row.Cells[6].Value);
var stream = new MemoryStream(data);
pictureBox1.Image = Image.FromStream(stream);
Can someone help me 3 days into this problem and I can't solve it.

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.

Linq To Sql duplicate a row in update case

I have a single entity that always duplicate a row when it needs to update:
protected static Task RegisterToDisc(Task task)
{
try
{
using (DataContext context = new DataContext())
{
//this will print an actual existing id from the db
_log.Debug(task.ID);
context.Tasks.InsertOnSubmit(task);
context.SubmitChanges();
}
}
catch(Exception e)
{
//...
}
return task;
}
When I print the id before the save, it is actually prints out an id that is really exists in the db.
this is the table:
CREATE TABLE [dbo].[TaskSet](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Message] [nvarchar](max) NOT NULL,
[Result] [nvarchar](max) NOT NULL,
[Status] [int] NOT NULL,
[Priority] [int] NOT NULL,
[Name] [nvarchar](max) NOT NULL,
[DateTimeAsked] [datetime] NOT NULL,
[DateTimePerfomed] [datetime] NOT NULL,
[SessionID] [nvarchar](max) NOT NULL,
CONSTRAINT [PK_TaskSet] 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
Edit
The task is comming from the database already, task.ID contains a number that is exists in the database, how come Linq inserts an entity with PK that is not null and in the db already.
in java hibernate you neet to context.insertOrUpdate(task); and it will decide what to do by the primary key.
InsertOnSubmit always marks the object for insertion. if you want to update the object u need to read it from database like
var objToUpdate = context.Tasks.SingleOrDefault(x=>x.Id == Id);
objToUpdate.Property1 = "updated value";
objToUpdate.Property2 = "updated value";
//do it for all properties that need updating
context.SubmitChanges();//since the object is tracked by context it will automatically generate sql to reflect update in db

Monthly billing system - query to get list of defaulters who have not paid their dues by today

this is the customers table, column 'C_BillingDay' indicates on which day the bill are due monthly for example if value is 4 thn billing due date of that customer is 4rth of each month. he has to pay his dues on 4rth ..
CREATE TABLE [dbo].[Customers](
[CID] [int] IDENTITY(1,1) NOT NULL,
[C_Name] [varchar](50) NULL,
[C_EmailID] [varchar](20) NULL,
[C_MobileNo] [varchar](20) NULL,
[C_PhoneNo] [varchar](20) NULL,
[C_HomeAddress] [varchar](max) NULL,
[C_ServiceArea] [int] NULL,
[C_AccountStatus] [int] NULL,
[C_IPAdress] [varchar](50) NULL,
[C_MACAddress] [varchar](50) NULL,
[C_Package] [int] NULL,
[C_BillingDay] [int] NULL,
[Balance] [float] NULL,
[C_AccountCreated] [datetime] NULL,
[C_AccountModified] [datetime] NULL,
payments' table:
TABLE [dbo].[Payments](
[PID] [int] IDENTITY(1,1) NOT NULL,
[CID] [int] NULL,
[Amount] [int] NULL,
[PaymentType] [int] NULL,
[Details/Comments] [varchar](max) NULL,
[DateTimeRecieved] [datetime] NULL,
[DateTimeModified] [datetime] NULL,
please help me quering all the defaulters who have not paid their dues on time by today ...
i have been trying with similar functions like DATEADD(MONTH,-1,GETDATE()) but they are not giving desired results :S
select * from Customers,payments
where Payments.DateTimeRecieved
NOT BETWEEN GETDATE() AND DATEADD(MONTH,-1,GETDATE())
From the limited system information given, I suspect there would be two relevant processes.
The first a daily job which does an UPDATE on the [Balance] column for all records in [Customers] based on [C_Package] (perhaps this indicates a monthly fee stored elsewhere), [C_AccountStatus] (perhaps indicating whether they are active), [C_BillingDay], and todays date.
Once that is done all you need to do is
SELECT [CID] FROM [dbo].[Customers] WHERE [Balance] > 0
Hope this helps.
Edit ...
To select Customers who haven't made a payment (though the logic seems flawed):
SELECT c.[CID]
FROM [Customers] c
WHERE c.[CID] NOT IN
(SELECT p.[CID] FROM [Payments] p
WHERE p.[DateTimeRecieved] BETWEEN GETDATE() AND DATEADD(MONTH,-1,GETDATE()))
(There's probably a way more elegant query than that!)
What about checking if the balance is not 0 and that today is the date of their payment. Something like:
select * from customers, payments where customers.balance > 0 and todays_date >= billdate;
its a bit abstract because i dont really know what language we are dealing with or what form your dates are in.
I am also making an assumption that they pay off their entire balance when they pay their dues

Categories