How to show different data to different users? - c#

Lets say parents have logged into system, and I would like to show them only their children details in GridView control. Up to one child can be studying at the same school. How can I achieve that? I've tried to join 3 tables in my database and display into GridView like this:
protected void Page_Load(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection("Data Source = DESKTOP-H7KQUT1; Initial Catalog = SAOS; Integrated Security = True");
String query = "SELECT s.FName FROM student s INNER JOIN student_parent sp ON s.SID = sp.SID INNER JOIN parent p ON sp.PID = p.PID WHERE p.PID = ";
SqlCommand cmd = new SqlCommand(query, con);
SqlDataReader dr;
con.Open();
dr = cmd.ExecuteReader();
GridView1.DataSource = dr;
GridView1.DataBind();
con.Close();
}
I can display student details successfully but I don't know how to display different student details to different parents. I stuck at this line:
String query = "SELECT s.FName FROM student s INNER JOIN student_parent sp ON s.SID = sp.SID INNER JOIN parent p ON sp.PID = p.PID WHERE p.PID = ";
Any Advises & References are appreciated

If I'm understanding your schema, it looks like you've mostly got it: you need to get the parent id (pid) by looking at which user has logged into your web app. Then you would use that information to most likely execute a query to lookup the pid. Then you pass that as a parameter to your SQL statement in the form 'where p.pid=#PID'. Here's some documentation on how to construct a query with parameters: https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.parameters?view=netframework-4.7.2
Just one word of warning: be very careful about how you get and verify the parent id (i.e. don't just pass it in as a URL parameter, make sure it's something you authenticate and keep on the server side so it can't easily subject you to spoofing and injection attacks)

Related

how to display data in crystal reports using mysql command conditional statement?

I am having a problem displaying conditional statement on my crystal reports. I want to display those customers who has a "Paid" status but it seems that my code didn't work because it still displays all of my data from database.
MySqlConnection conn;
MySqlCommand cmd;
MySqlDataAdapter adap;
conn = new MySqlConnection("Server=localhost; Database=order&billing; " +
"User ID=root; Password=; charset=utf8;"); conn.Open();
cmd = conn.CreateCommand();
cmd.CommandText = "select `order`.or_no,`order`.balance,`order`.totalprice, `order`.paid,customer.fname,customer.lname,customer.addr, customer.status, caterselected.catsel from `order` left join customer on `order`.custid=customer.custid left join caterselected on caterselected.nserveid=`order`.nserveid where `customer`.status='Paid'";
adap = new MySqlDataAdapter();
adap.SelectCommand = cmd;
DataSet1 custDB = new DataSet1();
custDB.Clear();
adap.Fill(custDB, "cust");
CrystalReport1 myReport = new CrystalReport1();
myReport.SetDataSource(custDB);
crystalReportViewer1.ReportSource = myReport;
And this is the output of my crystal reports
You are using somewhat strange filtering logic in your SQL query. This is the query.
select `order`.or_no,
`order`.balance,
`order`.totalprice,
`order`.paid,
customer.fname,
customer.lname,
customer.addr,
customer.status,
caterselected.catsel
from `order`
left join customer on `order`.custid=customer.custid
left join caterselected on caterselected.nserveid=`order`.nserveid
where `customer`.status='Paid'
This where clause pulls selects customer rows with a paid status, and incidentally converts the left join customer clause to an inner join customer clause by putting a filter condition on the left table.
But there's nothing in your tables (that I can see) requiring a customer with Paid status to have only orders with Paid status. You haven't explained your business logic sufficiently for us to understand what it means for a Paid customer to have an Unpaid order.
What happens if you use this WHERE clause instead?
where `order`.status='Paid'
myReport.SetDataSource(custDB.Tables(0));

How to display values into gridview from sql databese

In my database i have three tables. One For employs where i keep their names, ids, salary... In the second one named Project i keep id, location, name. in the third one named WorksOn i keep the id from employs and the id from project. In my Asp .Net web site in gridview i need to display the employee's name and the name of the project that he is working.
string connect =
WebConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString;
SqlConnection con = new SqlConnection(connect);
try
{
con.Open();
}
catch (Exception err)
{
string error = err.Message;
con.Close();
}
SqlCommand command = new SqlCommand();
command.Connection = con;
SqlDataReader reader;
command.CommandText = "SELECT * FROM WorksON ";
reader= command.ExecuteReader();
In data source in gridview if i choose to display the values from WorksOn table it shows the id from employs and the id from project but what i need is to show the names on the employs and project.
I know that i need to do something with dataset but i don't know who.
Your SQL command must JOIN the related tables. Something like:
SELECT * FROM WorksOn JOIN Employee on WorksOn.EmployeeId = Employee.Id
Note that you should not SELECT "*" (all columns). You should only SELECT those columns that are necessary to your data view for performance.
On your SQL command, you don't mention anything about Employs. You need to use a JOIN SQL command in order to get both the employee name and the company name.
And instead of using "SELECT * FROM...", consider using the columns name instead, because you're not trying to get all the columns display. And it will help us understand the name of the columns to further help you.
Use a JOIN query like this:
SELECT project.projectName, employee.Name
FROM (worksOn
INNER JOIN employee
ON (worksOn.employeeId = employee.employeeId))
INNER JOIN project
ON (project.projectId = employee.employeeId)
AND (worksOn.projectId = project.projectId)

sql command error in C#

I have written this code to retrieve some information from two tables in database. But when I run it I get this error
Column 'Eaten_food.Cardserial' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Code:
private void button8_Click(object sender, EventArgs e)
{
using (SqlConnection con = new SqlConnection(WF_AbsPres_Food.Properties.Settings.Default.DbConnectionString))
{
con.Open();
SqlDataAdapter a = new SqlDataAdapter("SELECT Eaten_food.Cardserial , Eaten_food.Date , Eaten_food.Turn , Avb_food_count , Reserve_count from Reserve inner join Eaten_food on Reserve.Cardserial = Eaten_food.Cardserial group by Eaten_food.Date", con);
SqlCommandBuilder comdBuilder = new SqlCommandBuilder(a);
DataTable t = new DataTable();
//t.Locale = System.Globalization.CultureInfo.InvariantCulture;
a.Fill(t);
bindingSource3.DataSource = t;
/// bind the grid view with binding source
Reserve_dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader);
Reserve_dataGridView.ReadOnly = true;
Reserve_dataGridView.DataSource = bindingSource3;
Reserve_dataGridView.DataSource = t;
con.Close();
}
}
How can I solve it?
The problem is your sql query. If you use Group By you cannot select columns that are not grouped by or that are not aggregated(f.e. by using Min/Max/Avg/Count).
So you could make it working for example in this way, change your old query here:
SELECT eaten_food.cardserial,
eaten_food.date,
eaten_food.turn,
avb_food_count,
reserve_count
FROM reserve
INNER JOIN eaten_food
ON reserve.cardserial = eaten_food.cardserial
GROUP BY eaten_food.date
to:
SELECT MIN(eaten_food.cardserial)AS Cardserial,
eaten_food.date,
MIN(eaten_food.turn) AS Turn,
SUM(avb_food_count) AS SumFoodCount,
SUM(reserve_count) AS SumReserveCount
FROM reserve
INNER JOIN eaten_food
ON reserve.cardserial = eaten_food.cardserial
GROUP BY eaten_food.date
You have a problem with you SQL statement itself. I would copy it to SQL management studio and debug it.
The group function is to create summary rows and because of that your select columns would either need to be part of the group by clause or a summary type of statmet like sum(x) or count(x)
The following might work..
SELECT Eaten_food.Cardserial ,
Eaten_food.Date ,
Count(Eaten_food.Turn) ,
sum(Avb_food_count) ,
sum(Reserve_count)
FROM Reserve
INNER JOIN Eaten_food ON Reserve.Cardserial = Eaten_food.Cardserial
GROUP BY Eaten_food.Date, Eaten_food.CardSerial

Populating a dropdown list from database

I have a asp.net page listing products (pulled from a database) with edit/delete buttons. The user can edit the product by clicking the edit button. I've been able to pull in data from the db to the textboxes based on the product selected. However, I am getting duplicate items in the dropdown box. It's only supposed to have 32 items and has 160 items (each item is appearing 5 times). I've used Items.Clear() but am still getting duplicates. Also the dropbox just shows the first item in the list rather than the appropriate item for that product that is currently in the db. Can anyone see what I may be doing wrong?
Thanks.
protected void Page_Load(object sender, EventArgs e)
{
this.Master.HighlightNavItem("Products");
string Mode = (Request.QueryString["Mode"]);
//Upon opening page, if this is an edit to existing product (populate product data)
if (Mode == "E")
{
if (!IsPostBack)
{
int ProductID = Int32.Parse(Request.QueryString["ID"]);
//Declare the connection object
SqlConnection Conn = new SqlConnection();
Conn.ConnectionString = ConfigurationManager.ConnectionStrings["MyDatabase"].ConnectionString;
//Connect to the db
Conn.Open();
//Define the query
//string sql = "SELECT dbo.Vendor.VendorName, dbo.Vendor.VendorID, dbo.Product.ProductName, dbo.Product.ProductNumber, dbo.lu_Category.CategoryID, dbo.lu_Category.Description FROM dbo.Product INNER JOIN dbo.Vendor ON dbo.Product.VendorID = dbo.Vendor.VendorID INNER JOIN dbo.lu_Category ON dbo.Product.CategoryID = dbo.lu_Category.CategoryID WHERE ProductID=#ProductID";
string sql = "SELECT ProductName, ProductNumber, ProductDescription, Cost, Markup, Unit, QtyOnHand, ShippingWeight, dbo.Vendor.VendorID, VendorName, dbo.lu_Category.CategoryID, Description FROM Vendor, Product, lu_Category WHERE ProductID=#ProductID";
//Declare the Command
SqlCommand cmd = new SqlCommand(sql, Conn);
//Add the parameters needed for the SQL query
cmd.Parameters.AddWithValue("#ProductID", ProductID);
//Declare the DataReader
SqlDataReader dr = null;
//Fill the DataReader
dr = cmd.ExecuteReader();
//Loop through the DataReader
ddlVendor.Items.Clear();
while (dr.Read())
{
txtProductName.Text = dr["ProductName"].ToString();
txtProductNo.Text = dr["ProductNumber"].ToString();
txtDescription.Text = dr["ProductDescription"].ToString();
txtCost.Text = dr["Cost"].ToString();
txtMarkup.Text = dr["Markup"].ToString();
txtUnit.Text = dr["Unit"].ToString();
txtQty.Text = dr["QtyOnHand"].ToString();
txtWeight.Text = dr["ShippingWeight"].ToString();
ListItem li = new ListItem();
li.Text = dr["VendorName"].ToString();
li.Value = dr["VendorID"].ToString();
ddlVendor.Items.Add(li);
You should change your SQL query and remove the , type of joins.
Then test your query directly in your database to make sure you don't get doubles.
The rest of your code looks fine so i'm sure testing your query will solve your problem.
Do not use Comma Joins it's deprecated.
I think you should have used inner or outer join to get your data. With ',' separated joins you are receiving data from both tables. like 32 rows of one table are getting appneded with 5 rows of other table.

Need help finding a good design and schema

I want to make an all in one query, or even a two step query that pulls from 3 tables.
Table #1: Games - this table holds a type of game and has a description of the game etc.
Table #2: GameProfiles - this holds an id from the table 'Games', so they both have a GamesId column. This table holds Games won, Games Lost, etc etc
Table #3: Games_WhateverGame - this is not a specific table, there are multiple tables, for instance if I have a game BasketBall, there is going to be a seperate table for it called Games_BasketBall and it has custom columns depending on the game. For example, Basketball would have a column for rebounds. This table would have its own primary key id.
I can easily pull the Games and GameProfiles together using an inner join on their common "GameId" column, but how do I make it so I can also pull 'Games_BasketBall' also in the same query, dynamically depending on the GamesId. I may be structuring this wrong, so I am open to suggestions. I just cant seem to think of a really fluid way of making this work correctly because each game will have different profile entities regardless so I want to make the relations to each table easy so I can pull everything in one query.
This code has the query WITHOUT the relation on to Games_Basketball, I want to be able to pull it all into one reader so it has the information correct.
using (SqlConnection myConnection = new SqlConnection(myConnectionString))
{
myConnection.Open();
String selectSql = "SELECT * FROM aspnet_GameProfiles INNER JOIN aspnet_Games ON aspnet_GameProfiles.GameId = aspnet_Games.GameId WHERE UserId = #UserId";
SqlCommand myCommand = new SqlCommand(selectSql, myConnection);
myCommand.Parameters.AddWithValue("#GameProfile", UserId);
reader = myCommand.ExecuteReader();
gameTable.DataSource = reader;
gameTable.DataBind();
myConnection.Close();
}
For yours current shema I would go for something like:
public enum GameType { Basketball, Snooker, ... }
void BindGameData(GameType gameType)
{
[ sql connection code ]
StringBuilder sb = new StringBuilder();
// those constant parts should be stored outside in config file
sb.append("SELECT * FROM aspnet_GameProfiles INNER JOIN aspnet_Games ON aspnet_GameProfiles.GameId = aspnet_Games.GameId ");
sb.append("INNER JOIN ");
sb.append("aspnet_" + gameType.toString()); // adopt to yours naming pattern
sb.append("ON aspnet_Games.GameId = ");
sb.append("aspnet_" + gameType.toString() + ".GameId");
sb.append("WHERE UserId = #UserId");
String selectSql = sb.toString();
[rest of yours sql connection code]
}
You could also use MARS (Mulitple Active Result Sets) to accomplish your goal. In MARS you use two sqldatareader at the same time.
Here is a small sample:
SqlDataReader rdrone = null;
SqlDataReader rdrtwo = null;
string connectionstring = "server=sugandha;initial catalog = Employeedetail;uid = sa;pwd= sa";MultipleActiveResultSets = true;
SqlConnection con = new SqlConnection(connectionstring);
SqlCommand cmdone = new SqlCommand("select * from Employee", con);
SqlCommand cmdtwo = new SqlCommand("select * from Employeedept", con);
con.Open();
rdrone = cmdone.ExecuteReader();
DataTable dtone = new DataTable();
dtone.Load(rdrone);
dataGridView1.DataSource = dtone;
rdrtwo = cmdtwo.ExecuteReader();
DataTable dttwo = new DataTable();
dttwo.Load(rdrtwo);
dataGridView2.DataSource = dttwo;
con.Close();
If you want to get all the information for all games at one time, it's not practical to do that in one query. And, you know, the user doesn't want to wait for you to do, say, 135 LEFT JOIN operations to get information from all the game "whatever" tables.
So, even though it's possible, it's not practical, and you really probably don't want to do that anyway. The user isn't likely to want to read through all that data, right?
Show just what the user needs, just when the user needs it. If the user clicks on "basketball", then you can query a view that has already joined the two or three tables you need to display information about the "basketball" game.

Categories

Resources