I am working on simple CRUD application where I have two tables:
Patient
CNIC (varchar 50 and PK)
Name (varchar 50)
PatientVaccines
Cnic (varchar 50 and FK)
VaccinationName (varchar)
VaccinationDate (varchar)
CenterAddress (varchar)
I know making string as PK, FK is not a good approach but this is my requirement.
I have a PatientDBContext class where I perform CRUD operations:
public class PatentDBContext
{
string cs = ConfigurationManager.ConnectionStrings["Myconnection"].ConnectionString;
public List<Patient> getPatients()
{
List<Patient> PatientList = new List<Patient>();
SqlConnection con = new SqlConnection(cs);
string query = "SELECT p.CNIC, p.Name, pv.cnic, pv.VaccinationName, pv.VaccinationDate, pv.CenterAddress FROM Patient AS p JOIN PatientVaccines AS pv ON p.CNIC = pv.cnic";
SqlCommand cmd = new SqlCommand(query, con);
con.Open();
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
Patient p = new Patient();
p.CNIC = dr["CNIC"].ToString();
p.Name = dr["Name"].ToString();
p.VaccinationName = dr["VaccinationName"].ToString();
//p.VaccinationDate = dr["VaccinationDate"].ToString();
p.CentreAddress = dr["CenterAddress"].ToString();
PatientList.Add(p);
}
con.Close();
return PatientList;
}
public bool AddPatient(Patient pat)
{
SqlConnection con = new SqlConnection();
SqlCommand cmd = new SqlCommand("spAddPatient", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#CNIC", pat.CNIC);
cmd.Parameters.AddWithValue("#Name", pat.Name);
cmd.Parameters.AddWithValue("#VaccinationName", pat.VaccinationName);
cmd.Parameters.AddWithValue("#VaccinationDate", pat.VaccinationDate);
cmd.Parameters.AddWithValue("#CenterAddress", pat.CentreAddress);
con.Open();
int i = cmd.ExecuteNonQuery();
con.Close();
if (i > 0)
{
return true;
}
else
{
return false;
}
}
public bool UpdatePatient(Patient pat)
{
SqlConnection con = new SqlConnection();
string query = "UPDATE PatientVaccines SET VaccinationName = #VaccinationName, VaccinationDate = #VacinationDate, CenterAddress = #CenterAddress WHERE Cnic = #Cnic";
SqlCommand cmd = new SqlCommand(query, con);
//cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#CNIC", pat.CNIC);
//cmd.Parameters.AddWithValue("#Name", pat.Name);
cmd.Parameters.AddWithValue("#VaccinationName", pat.VaccinationName);
cmd.Parameters.AddWithValue("#VaccinationDate", pat.VaccinationDate);
cmd.Parameters.AddWithValue("#CenterAddress", pat.CentreAddress);
con.Open();
int i = cmd.ExecuteNonQuery();
con.Close();
if (i > 0)
{
return true;
}
else
{
return false;
}
}
}
Errors is this class is in getPatient() function I comment it out p.VaccinationDate that shows an error that I cannot convert implicitly type string to DateTime, how do I convert it to DateTime?
I have another function names AddPatient()that now show any error or bug but when I click submit button after input records it doesn't perform any action.
HomeController
public class HomeController : Controller
{
// GET: Home
public ActionResult Index()
{
PatentDBContext db = new PatentDBContext();
List<Patient> obj = db.getPatients();
return View(obj);
}
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(Patient pat)
{
try
{
if (ModelState.IsValid == true)
{
PatentDBContext context = new PatentDBContext();
bool check = context.AddPatient(pat);
if (check == true)
{
TempData["InsertMessage"] = "Data Inserted..";
}
else
{
TempData["FailureMessage"] = "Data Not Inserted";
}
ModelState.Clear();
return RedirectToAction("Index");
}
return View();
}
catch
{
return View();
}
}
public ActionResult Edit(string Cnin)
{
PatentDBContext context = new PatentDBContext();
//string str = Cnin.ToString();
var row = context.getPatients().Find(model => model.CNIC = Cnin);
return View(row);
}
}
Here I also can't convert implicitly type string to bool
var row = context.getPatients().Find(model => model.CNIC = Cnin);
and finally this is my stored procedure:
ALTER PROCEDURE [dbo].[spAddPatient]
(#CNIC varchar(50),
#Name varchar(50),
#VaccinationName varchar(50),
#VaccinationDate varchar(50),
#CenterAddress varchar(50))
AS
BEGIN
INSERT INTO Patient (CNIC, Name)
VALUES (#CNIC, #Name)
INSERT INTO PatientVaccines (Cnic, VaccinationName, VaccinationDate, CenterAddress)
VALUES (#Cnic, #VaccinationName, #VaccinationDate, #CenterAddress)
END
I pretty sure that you are very new in this technology as there are some basic mistake. I am mentioning some common mistake below:
You should not use varchar as primary key instead use int
Make a relation in both parent and child table using int column.
Do not use varchar for date field, instead use DateTime.
I redesigned two tables as below:
Patient Table
CREATE TABLE [dbo].[Patient](
[Id] [int] IDENTITY(1,1) NOT NULL,
[CNIC] [varchar](50) NOT NULL,
[Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_Patient] 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
I introduce new column Id that set as IDENTITY so that this
column will get value automatically like 1, 2, 3
PatientVaccines Table
CREATE TABLE [dbo].[PatientVaccines](
[Id] [int] IDENTITY(1,1) NOT NULL,
[VaccinationName] [varchar](50) NULL,
[VaccinationDate] [datetime] NULL,
[CenterAddress] [varchar](50) NULL,
[PatientId] [int] NOT NULL,
CONSTRAINT [PK_PatientVaccines] 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
I introduce two new columns Id and PatientId. when you insert a patient, the Id field will get a number automaticaly and that id will be inserted into PatientVaccines Table as PatientId so that you can find the relational data. Also I used datetime for VaccinationDate.
FOREIGN KEY CONSTRAINT
ALTER TABLE [dbo].[PatientVaccines] WITH CHECK ADD CONSTRAINT [FK_PatientVaccines_Patient] FOREIGN KEY([PatientId])
REFERENCES [dbo].[Patient] ([Id])
This is a constraint or rules that will restrict you to insert data that is not relational. for example: you do not have a record of patient with Id 101 but you are trying to insert PatientVaccines record with PatientId 101 then this rule will restrict you to do that.
Here is the Sql Diagram of Two tables
By doing the above, you need to update your Stored Procedure as below:
CREATE PROCEDURE [dbo].[spAddPatient]
(#CNIC varchar(50),
#Name varchar(50),
#VaccinationName varchar(50),
#VaccinationDate datetime,
#CenterAddress varchar(50))
AS
BEGIN
INSERT INTO Patient (CNIC, Name)
VALUES (#CNIC, #Name)
INSERT INTO PatientVaccines (PatientId, VaccinationName, VaccinationDate, CenterAddress)
VALUES (##Identity, #VaccinationName, #VaccinationDate, #CenterAddress)
END
Here is the complete C# Code where I made some correction
public class PatentDBContext
{
string cs = ConfigurationManager.ConnectionStrings["Myconnection"].ConnectionString;
public List<Patient> getPatients()
{
List<Patient> PatientList = new List<Patient>();
SqlConnection con = new SqlConnection(cs);
string query = "SELECT p.CNIC, p.Name, pv.VaccinationName, pv.VaccinationDate, pv.CenterAddress FROM Patient AS p JOIN PatientVaccines AS pv ON p.Id = pv.PatientId";
SqlCommand cmd = new SqlCommand(query, con);
con.Open();
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
Patient p = new Patient();
p.CNIC = dr["CNIC"].ToString();
p.Name = dr["Name"].ToString();
p.VaccinationName = dr["VaccinationName"].ToString();
p.VaccinationDate = Convert.ToDateTime(dr["VaccinationDate"]);
p.CenterAddress = dr["CenterAddress"].ToString();
PatientList.Add(p);
}
con.Close();
return PatientList;
}
public bool AddPatient(Patient pat)
{
SqlConnection con = new SqlConnection(cs);
SqlCommand cmd = new SqlCommand("spAddPatient", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#CNIC", pat.CNIC);
cmd.Parameters.AddWithValue("#Name", pat.Name);
cmd.Parameters.AddWithValue("#VaccinationName", pat.VaccinationName);
cmd.Parameters.AddWithValue("#VaccinationDate", pat.VaccinationDate);
cmd.Parameters.AddWithValue("#CenterAddress", pat.CenterAddress);
con.Open();
int i = cmd.ExecuteNonQuery();
con.Close();
if (i > 0)
{
return true;
}
else
{
return false;
}
}
public bool UpdatePatient(Patient pat)
{
SqlConnection con = new SqlConnection(cs);
string query = "UPDATE PatientVaccines SET VaccinationName = #VaccinationName, VaccinationDate = #VaccinationDate, CenterAddress = #CenterAddress WHERE PatientId = ( Select Id from Patient where Cnic = #Cnic)";
SqlCommand cmd = new SqlCommand(query, con);
cmd.Parameters.AddWithValue("#CNIC", pat.CNIC);
//cmd.Parameters.AddWithValue("#Name", pat.Name);
cmd.Parameters.AddWithValue("#VaccinationName", pat.VaccinationName);
cmd.Parameters.AddWithValue("#VaccinationDate", pat.VaccinationDate);
cmd.Parameters.AddWithValue("#CenterAddress", pat.CenterAddress);
con.Open();
int i = cmd.ExecuteNonQuery();
con.Close();
if (i > 0)
{
return true;
}
else
{
return false;
}
}
}
I believe your stored procedure is not correct, you can test it beforehand in the database.
// here you should use operator== instead of аssignment operator=
// Have in mind that .Find will throw an error if model with given Cnin is not found
var row = context.getPatients().Find(model => model.CNIC == Cnin);
How to convert a string to datetime object
Create a stored procedure
General advice, you can google the errors you get and find information about them
Related
It's the first time to use SqlDependency and i hope to find answer for my problem
The problem i'm facing is that SqlDependency_OnChange event not firing with no errors
i've enabled broker in database
ALTER DATABASE databsename SET ENABLE_BROKER;
and Changed database owner to sa
ALTER AUTHORIZATION ON databsename TO sa;
and here is my Create Table DDL
CREATE TABLE [dbo].[user_log](
[user_log_id] [bigint] NOT NULL,
[user_name] [nvarchar](100) NULL,
[action_type_id] [int] NULL,
[document_type_id] [int] NULL,
[document_id] [nvarchar](20) NULL,
[description] [nvarchar](200) NULL,
[action_date] [datetime] NULL,
[seen] [bit] NULL,
CONSTRAINT [PK_user_log] PRIMARY KEY CLUSTERED
(
[user_log_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]
and wrote this code in visual studio
public User_Actions_Log_Form()
{
InitializeComponent();
try
{
SqlClientPermission SCP = new SqlClientPermission(System.Security.Permissions.PermissionState.Unrestricted);
SCP.Demand();
}
catch (Exception)
{
throw;
}
DA.DataAccess DAL = new DA.DataAccess();
SqlDependency.Stop(DAL.MyConnectionString().ConnectionString);
SqlDependency.Start(DAL.MyConnectionString().ConnectionString);
}
DataTable dt = new DataTable();
public void SearchUserLog()
{
BL.UserLogBL usr_log_bl = new BL.UserLogBL();
usr_log_bl.UserName = CBUser.SelectedValue == null ? null : CBUser.SelectedValue.ToString();
usr_log_bl.ActionTypeID = CBActionType.SelectedValue == null ? null : CBActionType.SelectedValue.ToString();
usr_log_bl.DocumentTypeID = CBDocumentType.SelectedValue == null ? null : CBDocumentType.SelectedValue.ToString();
usr_log_bl.DateFrom = DTPFrom.Checked? DTPFrom.Value.Date:(DateTime?)null;
usr_log_bl.DateTo = DTPTo.Checked ? DTPTo.Value.Date.AddSeconds(86340) : (DateTime?)null;
DA.DataAccess DAL = new DA.DataAccess();
using (SqlConnection con = new SqlConnection(DAL.MyConnectionString().ConnectionString))
{
SqlCommand cmd = new SqlCommand();
if (con.State == ConnectionState.Closed)
{
con.Open();
}
cmd.Connection = con;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "dbo.ManageUserLog";
SqlParameter[] para = new SqlParameter[7];
para[0] = new SqlParameter("#check", "s");
para[1] = new SqlParameter("#user_name", usr_log_bl.UserName);
para[2] = new SqlParameter("#action_type_id", usr_log_bl.ActionTypeID);
para[3] = new SqlParameter("#document_type_id", usr_log_bl.DocumentTypeID);
para[4] = new SqlParameter("#date_from", usr_log_bl.DateFrom);
para[5] = new SqlParameter("#date_to", usr_log_bl.DateTo);
para[6] = new SqlParameter("#seen", usr_log_bl.Seen);
cmd.Parameters.AddRange(para);
var depenedency = new SqlDependency(cmd);
cmd.Notification = null;
depenedency.OnChange += new OnChangeEventHandler(sqlDependency_OnChange);
dt.Rows.Clear();
dt.Load(cmd.ExecuteReader(CommandBehavior.CloseConnection));
dataGridView1.DataSource = dt;
}
}
private void sqlDependency_OnChange(object sender, SqlNotificationEventArgs e)
{
SqlDependency SD = sender as SqlDependency;
SD.OnChange -= sqlDependency_OnChange;
if (OnNewUserActionsLogForm != null)
{
User_Actions_Log_Form_OnNewHome();
}
}
public delegate void New_User_Actions_Log_Form();
public event New_User_Actions_Log_Form OnNewUserActionsLogForm;
private void User_Actions_Log_Form_Load(object sender, EventArgs e)
{
OnNewUserActionsLogForm += new New_User_Actions_Log_Form(User_Actions_Log_Form_OnNewHome);
SearchUserLog();
}
private void User_Actions_Log_Form_OnNewHome()
{
ISynchronizeInvoke i = (ISynchronizeInvoke)this;
if (i.InvokeRequired)
{
New_User_Actions_Log_Form dd = new New_User_Actions_Log_Form(User_Actions_Log_Form_OnNewHome);
i.BeginInvoke(dd, null);
return;
}
SearchUserLog();
}
and this is the sql procedure which i called
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER proc [dbo].[ManageUserLog]
(
#user_name nvarchar(100) = null,
#action_type_id int = null,
#document_type_id int = null,
#date_from datetime = null,
#date_to datetime = null,
#seen bit = null
)
as
begin
select user_log_id,
[user_name],
dbo.GetActionTypeByID(action_type_id) as action_type,
dbo.GetDocumentTypeByID(document_type_id) as document_type,
document_id,
[description],
action_date,
seen
from dbo.user_log
where (#user_name is null or [user_name] = #user_name)
and (#action_type_id is null or action_type_id = #action_type_id)
and (#document_type_id is null or document_type_id = #document_type_id)
and (action_date between #date_from and #date_to)
and (seen = #seen)
end
so can anyone help me solving this problem
Below is a Minimal, Complete, and Verifiable example of a working Sqldependency using a simplified version of your WinForm app with hard-coded parameter values. I modified the stored procedure in your question to remove the function calls (invalid for SqlDependency notifications) and removed the #check SqlCommand parameter from the C# code since that parameter is not defined in the stored procedure.
This example works on my system so I expect it will fire the OnChange handler on your dev box when data are changed.
T-SQL setup code:
CREATE DATABASE YourDatabase;
GO
ALTER DATABASE YourDatabase SET ENABLE_BROKER;
GO
USE YourDatabase;
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[user_log](
[user_log_id] [bigint] NOT NULL,
[user_name] [nvarchar](100) NULL,
[action_type_id] [int] NULL,
[document_type_id] [int] NULL,
[document_id] [nvarchar](20) NULL,
[description] [nvarchar](200) NULL,
[action_date] [datetime] NULL,
[seen] [bit] NULL,
CONSTRAINT [PK_user_log] PRIMARY KEY CLUSTERED
(
[user_log_id] ASC
)
);
GO
INSERT INTO dbo.user_log(user_log_id, user_name, action_date, seen)
VALUES(1,'test', '2018-04-15T00:00:00', 1);
GO
CREATE proc [dbo].[ManageUserLog]
(
#user_name nvarchar(100) = null,
#action_type_id int = null,
#document_type_id int = null,
#date_from datetime = null,
#date_to datetime = null,
#seen bit = null
)
as
begin
select user_log_id,
[user_name],
--dbo.GetActionTypeByID(action_type_id) as action_type,
--dbo.GetDocumentTypeByID(document_type_id) as document_type,
document_id,
[description],
action_date,
seen
from dbo.user_log
where (#user_name is null or [user_name] = #user_name)
and (#action_type_id is null or action_type_id = #action_type_id)
and (#document_type_id is null or document_type_id = #document_type_id)
and (action_date between #date_from and #date_to)
and (seen = #seen)
end
GO
GRANT EXEC ON dbo.ManageUserLog TO public;
GO
C# WinForm code:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
static string connectionString = #"Data Source=.;Initial Catalog=YourDatabase;Integrated Security=SSPI";
public Form1()
{
InitializeComponent();
SqlDependency.Start(connectionString);
SearchUserLog();
}
public void SearchUserLog()
{
DataTable dt = new DataTable();
using (SqlConnection con = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand())
{
con.Open();
cmd.Connection = con;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "dbo.ManageUserLog";
SqlParameter[] para = new SqlParameter[6];
para[0] = new SqlParameter("#user_name", "test");
para[1] = new SqlParameter("#action_type_id", System.DBNull.Value);
para[2] = new SqlParameter("#document_type_id", System.DBNull.Value);
para[3] = new SqlParameter("#date_from", DateTime.Parse("2018-04-15"));
para[4] = new SqlParameter("#date_to", DateTime.Parse("2018-04-16"));
para[5] = new SqlParameter("#seen", 1);
cmd.Parameters.AddRange(para);
var depenedency = new SqlDependency(cmd);
depenedency.OnChange += new OnChangeEventHandler(sqlDependency_OnChange);
dt.Rows.Clear();
dt.Load(cmd.ExecuteReader(CommandBehavior.CloseConnection));
}
}
private void sqlDependency_OnChange(object sender, SqlNotificationEventArgs e)
{
MessageBox.Show($"OnChange Event fired. SqlNotificationEventArgs: Info={e.Info}, Source={e.Source}, Type={e.Type}\r\n");
//resubscribe only if valid
if ((e.Info != SqlNotificationInfo.Invalid)
&& (e.Type != SqlNotificationType.Subscribe))
{
SearchUserLog();
}
}
}
}
T-SQL code to fire OnChange handler:
DECLARE #ID int = (SELECT MAX(user_log_id)+1 FROM dbo.user_log);
INSERT INTO dbo.user_log(user_log_id, user_name, action_date, seen)
VALUES(#ID,'test', '2018-04-15T00:00:00', 1);
GO
I have a table:
CREATE TABLE [dbo].[DeliveryData](
[DeliveryId] [int] IDENTITY(1,1) NOT NULL,
...
CONSTRAINT [PK_DeliveryData] PRIMARY KEY CLUSTERED
(
[DeliveryId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
And code:
public void GetPrimaryKeyColumns(SqlConnection conn) {
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "select * from [dbo].[DeliveryData]";
SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SchemaOnly);
DataTable schema = reader.GetSchemaTable();
DataColumn[] columns = schema.PrimaryKey;
...
}
cmd, reader, and schema all look good, but columns ends up a zero length array. Shouldn't it contain "DeliveryId"? How can I get the primary column "DeliveryId"?
Thanks for the help!
Blake
MSSQL doesn't return correct primary key information in all cases using GetSchemaTable. (Not too surprising. For example, almost all DB vendors support ODBC better than MS.) The following query, however, does work:
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS as tc
LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE as kcu
ON kcu.CONSTRAINT_CATALOG = tc.CONSTRAINT_CATALOG
AND kcu.CONSTRAINT_SCHEMA = tc.CONSTRAINT_SCHEMA
AND kcu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME
AND kcu.TABLE_CATALOG = tc.TABLE_CATALOG
AND kcu.TABLE_SCHEMA = tc.TABLE_SCHEMA
AND kcu.TABLE_NAME = tc.TABLE_NAME
WHERE tc.CONSTRAINT_TYPE ='PRIMARY KEY'
AND tc.TABLE_SCHEMA = 'dbo'
AND tc.TABLE_NAME = 'DeliveryData'
ORDER BY ORDINAL_POSITION;
The schema table is not the DeliveryData table. You must inspect the schema table where the IsKey column is true and then grab the ColumnName field. You can then use that find the real column on a regular data table.
Update
GetSchemaTable() returns a data table of metadata information which you can see in the documentation: https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.getschematable(v=vs.110).aspx
You end up with as many rows in the returned DataTable as you would have columns in the query if you were to run the query. Here is a partial screenshot of the schema table I get from a test table in my database. Notice every column is now a row, and the IsKey field will tell you if the column is a key column:
If you want to use the PrimaryKey property on a DataTable do not use GetSchemaTable(), just use a SqlDataAdapter to fill a regular DataTable.
Update 2
use CommandBehavior.KeyInfo instead of CommandBehavior.SchemaOnly
Using SMO
using Microsoft.SqlServer.Management.Smo;
....
Server svr = new Server("Your Server Name");
Database db = svr.Databases["Your Database Name"];
Table tbl = db.Tables["DeliveryData"];
foreach (Column c in tbl.Columns)
{
bool isAKeyColumn = c.InPrimaryKey
}
This is a complete solution:
public List<string> GetPrimaryKeyColumns(DbConnection conn, string schema, string table) {
DbCommand cmd = conn.CreateCommand();
DbParameter p = cmd.CreateParameter();
p.ParameterName = "#schema";
p.Value = schema;
p.DbType = DbType.String;
p.Direction = ParameterDirection.Input;
cmd.Parameters.Add(p);
p = cmd.CreateParameter();
p.ParameterName = "#table";
p.Value = table;
p.DbType = DbType.String;
p.Direction = ParameterDirection.Input;
cmd.Parameters.Add(p);
cmd.CommandText = #"SELECT kcu.COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS as tc
LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE as kcu
ON kcu.CONSTRAINT_CATALOG = tc.CONSTRAINT_CATALOG
AND kcu.CONSTRAINT_SCHEMA = tc.CONSTRAINT_SCHEMA
AND kcu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME
-- AND kcu.TABLE_CATALOG = tc.TABLE_CATALOG doesn't work on MySQL
AND kcu.TABLE_SCHEMA = tc.TABLE_SCHEMA
AND kcu.TABLE_NAME = tc.TABLE_NAME
WHERE tc.CONSTRAINT_TYPE ='PRIMARY KEY'
AND tc.TABLE_SCHEMA = #schema
AND tc.TABLE_NAME = #table
ORDER BY ORDINAL_POSITION";
DbDataReader reader = cmd.ExecuteReader(CommandBehavior.KeyInfo);
List<string> res = new List<string>();
while (reader.Read()) {
var str = reader[0];
if (str != System.DBNull.Value)
res.Add((string) str);
}
reader.Dispose();
cmd.Dispose();
return res;
}
C#:
protected void btnsearch_Click(object sender, EventArgs e)
{
SqlConnection con = Connection.DBconnection(); {
SqlCommand com = new SqlCommand("sp_studentresult", con);
com.CommandType = CommandType.StoredProcedure;
com.Parameters.AddWithValue("#id", textstudentid.Text);
com.Parameters.AddWithValue("#id_student", textstudentid.Text.Trim());
SqlParameter retval = new SqlParameter("#output", SqlDbType.VarChar, 50);
com.Parameters.AddWithValue("#tamil", txttamil.Text.Trim());
com.Parameters.AddWithValue("#english", txtenglish.Text.Trim());
com.Parameters.AddWithValue("#maths", txtmaths.Text.Trim());
com.Parameters.AddWithValue("#science", txtscience.Text.Trim());
com.Parameters.AddWithValue("#socialScience", txtsocialscience.Text.Trim());
retval.Direction = ParameterDirection.Output;
com.Parameters.Add(retval);
com.ExecuteNonQuery();
string Output = retval.Value.ToString();
textstudentid.Text = string.Empty;
txttamil.Text = string.Empty;
txtenglish.Text = string.Empty;
txtmaths.Text = string.Empty;
txtscience.Text = string.Empty;
txtsocialscience.Text = string.Empty;
SqlDataAdapter adp = new SqlDataAdapter(com);
DataSet ds = new DataSet();
adp.Fill(ds);
if (ds.Tables[0].Rows.Count > 0)
{
tblid.Visible = true;
txtid.Text = ds.Tables[0].Rows[0]["id"].ToString();
txttamil.Text = ds.Tables[0].Rows[0]["Tamil"].ToString();
txtenglish.Text = ds.Tables[0].Rows[0]["English"].ToString();
txtmaths.Text = ds.Tables[0].Rows[0]["Maths"].ToString();
txtscience.Text = ds.Tables[0].Rows[0]["Science"].ToString();
txtsocialscience.Text = ds.Tables[0].Rows[0]["SocialScience"].ToString();
}
else
{
tblid.Visible = false;
output.Text = Output;
}
}
What I have done:
Step 1
When I enter invalid id (which means id doesnot contain in student table) and search, it shows "doesn't exist".
Step 2
When I enter valid id (which means id contains in student and also contain in studentresult table) and search, it shows student marks, if I want to edit the marks and update, so it shows "marks updated".
Step 3
But when I enter id (which means id contains in student but doesn't contain in studentresult table) and search, it works updated function again with all the textboxes contains 0, instead it works insertion.
May I know, what my mistake in the above code?
Can anyone guide me?
I'm struggling for an hour, I'm beginner in .net.
Thanks,
sp_studentresult is broken: it should not insert into studentresult if there already is a row for the given id. Just add
AND NOT EXISTS (SELECT * FROM studentresult WHERE id_student=#id_student)
to
ELSE IF EXISTS (SELECT * FROM student WHERE id=#id_student)
Resulting to:
ALTER PROCEDURE sp_studentresult
(
#id int,
#output varchar(50) output,
#id_student varchar(50),
#Tamil Varchar (100),
#English varchar (50),
#Maths Varchar (50),
#Science Varchar (50),
#SocialScience Varchar (50)
)
AS
IF NOT EXISTS (SELECT * FROM student WHERE id=#id_student)
BEGIN
SET #output='Doesn not EXIST'
END
ELSE IF EXISTS (SELECT * FROM student WHERE id=#id_student)
AND NOT EXISTS (SELECT * FROM studentresult WHERE id_student=#id_student)
BEGIN
INSERT into studentresult (id_student,Tamil,English,Maths,Science,SocialScience) values (#id_student,#Tamil,#English,#Maths,#Science,#SocialScience)
SET #output='Inserted'
END
SELECT * from studentresult where id_student=#id
I created a procedure that returns the ID of the Question based on the input text
ALTER PROCEDURE [dbo].[GetQuestionIDbyTekst]
(
#Tekst nvarchar(100)
)
AS
DECLARE #QuestionID int
SELECT QuestionID
FROM dbo.Questions
WHERE Tekst = #Tekst
RETURN #QuestionID
and I have a problem in getting the value of the QuestionID:
public static int getQuestionID(Question p)
{
using (Entities dm = new Entities())
{
return dm.GetQuestionIDbyTekst(p.Tekst);
}
}
Make the #QuestionID as Output parameter. Also you need to assign the result to #QuestionID
ALTER PROCEDURE [dbo].[GetQuestionIDbyTekst]
(
#Tekst nvarchar(100),
#QuestionID INT OUTPUT
)
AS
BEGIN
DECLARE #QuestionID int
SELECT #QuestionID = QuestionID FROM dbo.Questions WHERE Tekst = #Tekst
END
please try this:
ALTER PROCEDURE [dbo].[GetQuestionIDbyTekst]
(
#Tekst nvarchar(100)
)
AS
-- DECLARE #QuestionID int
SELECT QuestionID
FROM dbo.Questions
WHERE Tekst = #Tekst
-- RETURN #QuestionID
You can use your variant of the stored procedure.
And if you use ADO.NET and want to get return value, try this:
SqlConnection con = new SqlConnection(#"Data Source=localhost\***;Initial Catalog=***;Integrated Security=True;Persist Security Info=False;");
con.Open();
SqlCommand cmd = new SqlCommand("GetQuestionIDbyTekst", con);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add("#Tekst", System.Data.SqlDbType.NVarChar).Value = "eee";
SqlParameter returnPar = new SqlParameter();
returnPar.Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add(retturnPar);
cmd.ExecuteScalar();
var result = returnPar.Value;
If you use Entity Framework, you may use this variant:
public static int GetQuestionIDbyTekst(string question)
{
using (var context = new EfDbContext())
{
var test = new SqlParameter("#Tekst", question);
var resultParam = new SqlParameter("#result", SqlDbType.Int);
resultParam.Direction = ParameterDirection.Output;
context.Database.ExecuteSqlCommand("exec #result = [dbo].[testProc] #Tekst", resultParam, test);
return (int)resultParam.Value;
}
}
I am displaying categories in a dropdown list for adding products. When a product is to be added, you will have to select a category and Create Product or Update a previous product.
But my problem is that I get the following error:
No mapping exists from object type
System.Web.UI.WebControls.DropDownList to a known managed provider
native type.
Database Diagram:
ASPX.:
<p>Kategori</p>
<asp:DropDownList ID="DDCategories" runat="server" AutoPostBack="True">
</asp:DropDownList>
ASPX.CS.:
protected void Page_Load(object sender, EventArgs e)
{
//Dropdown Category Names From DB
if (!IsPostBack)
{
string sConstr = ConfigurationManager.ConnectionStrings["LLcateringConnectionString"].ConnectionString;
SqlConnection Conn = new SqlConnection(sConstr);
DataTable dt = new DataTable("tbl");
using (Conn)
{
Conn.Open();
SqlCommand comm = new SqlCommand("SELECT Name FROM Category", Conn);
SqlDataAdapter da = new SqlDataAdapter(comm);
da.Fill(dt);
}
DDCategories.DataSource = dt;
DDCategories.DataTextField = "Name";
DDCategories.DataBind();
}
}
protected void BtnUpdateOrCreate_Click(object sender, EventArgs e)
{
// Text in fields has to exist, if they are requierd
if (!string.IsNullOrWhiteSpace(TxtName.Text) /*&&
!string.IsNullOrWhiteSpace(TxtDescription.Text)*/)
{
// New the DataAccess and have all the parameteres here
DataAccess dataAccess = new DataAccess();
dataAccess.AddParameter("#Name", TxtName.Text);
dataAccess.AddParameter("#Category_ID", DDCategories);
dataAccess.AddParameter("#Description", TxtDescription.Text.ToNewline(false));
dataAccess.AddParameter("#UnitPrice", TxtPrice.Text);
dataAccess.AddParameter("#DiscountUnitPrice", TxtUnitDiscount.Text);
if (isCreate)
{
// Insert query
dataAccess.Execute(#"INSERT INTO [Product] ([Name], [Category_ID], [UnitPrice], [DiscountUnitPrice], [Description])
VALUES (#Name, #Category_ID, #UnitPrice, #DiscountUnitPrice, #Description)
INNER JOIN dbo.Product ON dbo.Category.ID = dbo.Product.Category_ID
ORDER BY [Name]
WHERE id = #id");
}
else
{
// Update query
dataAccess.AddParameter("#id", MenuID);
dataAccess.Execute(#"UPDATE [Product]
SET [Name] = #Name, [Category_ID] = #Category_ID, [UnitPrice] = #UnitPrice, [DiscountUnitPrice] = #DiscountUnitPrice, [Description] = #Description
WHERE id = #id");
//UPDATE [Product]
//SET [Name] = #Name, [Category_ID] = #Category_ID, [UnitPrice] = #UnitPrice, [DiscountUnitPrice] = #DiscountUnitPrice, [Description] = #Description
//INNER JOIN dbo.Product ON dbo.Category.ID = dbo.Product.Category_ID
//ORDER BY [Name]
//WHERE id = #id");
}
// Redirects to list
Response.Redirect(Request.Url.AbsolutePath);
}
else
LitStatus.Text = "Hey så indtast da noget!";
}
check this line
dataAccess.AddParameter("#Category_ID", DDCategories);
and replace with
dataAccess.AddParameter("#Category_ID", DDCategories.SelectedValue)