I am making a form in asp using C# and my task is to make a course and packages detail and insert the , i have make three tables one is Course which contain Id(pk) and Course-name, packages table contain Id(pk) and pkg-name and other table is Pkg-detail which contain Pkg-id(pk) and it is foreign key for Id in packages table and other attribute is course-id it is foreign key for course(ID) and my task is when i select pkg-name from drop down and course from check box from asp form that particular Id for pkg-name and Id for Course-name will insert in third table pkg-detail as i am new i have searched lot but cannot find related answer.
SqlCommand cmm = new SqlCommand("Pkc", con);
cmm.CommandType = CommandType.StoredProcedure;
cmm.Parameters.AddWithValue("#pname", drop1.SelectedValue);
cmm.Parameters.AddWithValue("#course", check1.SelectedValue);
con.Open();
cmm.ExecuteNonQuery();
con.Close();
CREATE PROCEDURE [dbo].[Pkc]
#course nvarchar(50),
#pname nvarchar(50)
AS
begin
insert into Pkg(CourseId)values((select Id from Courses where CourseName=#course));
insert into Pkg(PkgId) values ((select Id from PKgCode where PkgName=#pname))
end
You didn't mentioned your problem, but from your text it seems that you want to pass courceID and PackageID into your StoredProc, your code has a problem, since dropdown.SelectedValue is string by AddWithValue you will add two string parameter while I think they should be integer. So cast them as int or use other method that accepts type of parameter.
Edit
Base on comments it seems that your procedure should be like this:
CREATE PROCEDURE [dbo].[Pkc] #course nvarchar(50), #pname nvarchar(50)
AS
begin
declare #courceID int
declare #pkgID int
select #courceID = Id from Courses where CourseName=#course
select #pkgID = Id from PKgCode where PkgName=#pname
insert into Pkg-Detail(CourseId,PkgId) values(#courceID, #pkgID)
end
Related
I have a table which generates its primary key from a sequence (that just counts up from 0):
CREATE TABLE [dbo].[testTable](
[id] [int] NOT NULL,
[a] [int] NOT NULL,
CONSTRAINT [PK_testTable] PRIMARY KEY CLUSTERED ([id] ASC))
ALTER TABLE [dbo].[tblTestTable] ADD CONSTRAINT [DF_tblTestTable_id] DEFAULT (NEXT VALUE FOR [seq_PK_tblTestTable]) FOR [id]
I've used Visual Studio's O/R Designer to create the mapping files for the table; the id field is defined as:
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_id", DbType="Int NOT NULL", IsPrimaryKey=true)]
public int id {…}
and now I'm trying to insert data via LINQ.
var testTableRecord = new testTable()
{
a = 1,
};
db.Connection.Open();
db.testTables.InsertOnSubmit(testTableRecord);
db.SubmitChanges();
Console.WriteLine($"id: {testTableRecord.id}");
The problem I'm encountering is, that LINQ seems unable to handle the id generation via sequence as it sets the id implicitly to 0 when inserting.
When I set the id to CanBeNull, the insert fails because it tries to insert NULL into a non-nullable field.
When I set the id to IsDbGenerated, the insert works but it expects an IDENTITY field and tries to load the generated id with SELECT CONVERT(Int,SCOPE_IDENTITY()) AS [value]',N'#p0 int',#p0=1 and than sets the id in the object to null because SCOPE_IDENTITY() returns null…
I've been thinking about just using IsDbGenerated, destroying the LINQ object and querying the DB for the id, but I don't have anything unique to search for.
Unfortunately changing the id creation mechanism to IDENTITY is not an option.
Do I have to explicitly query the DB for the next sequence value and set the id manually?
Whats the best way to handle these inserts via LINQ?
PS: I need the id because I have to insert more data that uses the id as FK.
Looking at solutions from the raw sql perspective:
1.
INSERT INTO [dbo].[testTable] VALUES (NEXT VALUE FOR [dbo].[seq_PK_tblTestTable], 1)
Simply can't be done in LINQ to SQL as far as I can tell
2.
INSERT INTO [dbo].[testTable] (a) VALUES (1)
This can be achieved in LINQ to SQL by excluding the id property from the testTable entity.
If you need to retrieve ids from the table, you could create separate entities for inserting and querying:
public class testTableInsert {
[ColumnAttribute(...)]
public int a
}
public class testTableResult {
[ColumnAttribute(...)]
public int id
[ColumnAttribute(...)]
public int a
}
3.
DECLARE #nextId INT;
SELECT #nextId = NEXT VALUE FOR [dbo].[seq_PK_tblTestTable];
INSERT INTO [dbo].[testTable] VALUES (#nextId, 1)
As you mentioned, this can be essentially achieved by manually requesting the next id before each insert. If you go this route there are multiple ways to achieve it in your code, you can consider stored procedures or use the LINQ data context to manually execute the sql to retrieve the next sequence value.
Here's a code sample demonstrating how to extend the generated DataContext using partial methods.
public partial class MyDataContext : System.Data.Linq.DataContext
{
partial void InsertTestTable(TestTable instance)
{
using (var cmd = Connection.CreateCommand())
{
cmd.CommandText = "SELECT NEXT VALUE FOR [dbo].[seq_PK_TestTable] as NextId";
cmd.Transaction = Transaction;
int nextId = (int) cmd.ExecuteScalar();
instance.id = nextId;
ExecuteDynamicInsert(instance);
}
}
}
Once the above is implemented, you can safely insert entities like this, and they will generate the correct sequence id.
TestTable entity = new TestTable { a = 2 };
dataContext.TestTables.InsertOnSubmit(entity);
dataContext.SubmitChanges();
Your only hope is a pretty profound refactoring and use a stored procedure to insert records. The stored procedure can be mapped to the class's Insert method in the data context designer.
Using your table definition, the stored is nothing but this:
CREATE PROCEDURE InsertTestTable
(
#id int OUTPUT,
#a AS int
)
AS
BEGIN
INSERT dbo.testTable (a) VALUES (#a);
SET #id = (SELECT CONVERT(int, current_value)
FROM sys.sequences WHERE name = 'seq_PK_tblTestTable')
END
You can import this stored procedure into the context by dragging it from the Sql Object Explorer onto the designer surface, which will then look like this:
The next step is to click the testTable class and click the ellipses button for the Insert method (which got enabled by adding the stored procedure to the context):
And customize it as follows:
That's all. Now LINQ-to-SQL will generate a stored procedure call to insert a record, for example:
declare #p3 int
set #p3=8
declare #p5 int
set #p5=0
exec sp_executesql N'EXEC #RETURN_VALUE = [dbo].[InsertTestTable] #id = #p0 OUTPUT,
#a = #p1',N'#p0 int output,#p1 int,#RETURN_VALUE int output',
#p0=#p3 output,#p1=123,#RETURN_VALUE=#p5 output
select #p3, #p5
Of course you may have to wonder how long you're going to hang on to LINQ-to-SQL. Entity Framework Core has sequence support out of the box. And much more.
I do apologize, I know this question pops up a lot, but I'm afraid I just don't understand the answers I've read on the subject and was hoping someone could clear things up for me.
I have three tables:
Recipes (ID int primary identity, RecipeName varchar(20), Directions varchar(max), RecIngID int)
Ingredients (ID int primary identity, IngredientName varchar(30), Quantity int)
and a junction table, Recipe_Ingredients (RecipeID int foreign key references Recipe(ID), IngredientID int foreign key references Ingredient(ID)
Now, that being said, I need to create stored procedures for everything (because I'm creating an ntier program using asp.net MVC 4 and C#, blah blah blah....
But I have no clue how to write a stored procedure for inserting a new recipe into that table, and taking into account the relationship between the junction table Recipe_Ingredients and the Ingredient table.
Can someone please, PLEASE help me here? All the explanations I've read haven't really made sense. If there's something I'm doing wrong, please tell me.
for each ingredient call this stored procedure
create procedure insertIngredients
(
#name varchar,
#quantity int
)
as
insert into Ingredients (IngredientName, Quantity)
values (#name, #quantity)
select SCOPE_IDENTITY()
which inserts ingredient and returns it's newly inserted ID.
Store that ids into some variable (ie, List or comma delimited string).
After that, insert recipe calling procedure:
create procedure insertRecipe
(
#name varchar,
#directions varchar(max),
#RecIngID int
)
as
insert into Recipes (RecipeName, Directions, RecIngID)
values (#name, #directions, #RecIngID)
select SCOPE_IDENTITY()
also save ID which that procedure returns after insert.
And, as last step insert data into junction table using recipe ID and all those Ingredient ID's you previously inserted.
create procedure insertRecipeIngredients
(
#recipeID int,
#ingredientID int
)
as
insert into Recipe_Ingredients (RecipeID, IngredientID)
values (#recipeID, #ingredientID)
select SCOPE_IDENTITY()
in your c# code call procedures like this:
public int InsertIngredient(string name, int quantity)
{
SqlConnection conn = new SqlConnection("[your connection string goes here]");
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = "insertIngredients";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#name", name);
cmd.Parameters.AddWithValue("#quantity", quantity);
conn.Open();
int newlyInsertedId = (int) cmd.ExecuteScalar();
if (conn.State == System.Data.ConnectionState.Open)
conn.Close();
return newlyInsertedId;
}
Hi i'm having trouble with inserting incremented userid inside my db below is my table,stored proc,and my code.
CREATE TABLE [dbo].[Assignment2]
(
userID int PRIMARY KEY IDENTITY(1,1),
Name varchar(255) NOT NULL,
Age int NOT NULL,
Hobbies varchar(255)
)
and a stored procedure
ALTER PROCEDURE [db].[p_Assignment2_ins]
#userID int,
#Name nvarchar(100),
#Age int,
#Hobbies nvarchar(100)
AS
INSERT INTO [DB].[db].[Assignment2]
([Name]
,[Age]
,[Hobbies])
VALUES
(#Name
,#Age
,#Hobbies)
If ##Error <> 0
Return -1
Select #userID = ##Identity // this one just get the latest id that we inserted right?
Return 0
I have some question :
I want to know how do we insert the UserID from the code behind because If the table is empty at first shouldn't we insert a data first into the table
How do we generate an AutoIncrementID from codebehind and insert it
SqlConnection conn = new SqlConnection(ts.ConnMethod());
SqlCommand cmd = new SqlCommand("p_Assignment2_ins", conn);
cmd.CommandType = CommandType.StoredProcedure;
//I'm missing how we should add the IncrementedID
cmd.Parameters.AddWithValue("#Name", TextBox1.Text);
cmd.Parameters.AddWithValue("#Age", TextBox2.Text);
cmd.Parameters.AddWithValue("#Hobbies", TextBox3.Text);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
Any help is really appreciated thanks
Select #userID = ##Identity // this one just get the latest id that we inserted right?
No, you should use SCOPE_IDENTITY(). ##Identity returns the last id, yes, but not the last id from your insert. If you have a trigger, for example, that also produces an insert on a another table as a result of your insert, you will get the id inserted on the other table by that trigger.
Here's a nice article explaining the differences.
As far as inserting autoincrement values on your table; you can't do this unless you disable the constraint first but in essence, this shouldn't be necessary unless you are doing some sort of data import. In your scenario, you should be able to just insert values on the other columns except the identity field with autoincrement. The database will take care of inserting the appropriate value for you.
If you have AUTOINCREMENT field, you SHOULD NOT insert and generate values at all. DB is doing all by itself. So, remove the code that inserts ID-s
I have one login form like :
Username: Ashish
Password: Pass
Contact no: 1234567890
State: Maharashtra
Having two tables :
create table DGRegion
(DG_Regionno Int Identity (1,1) NOT Null constraint pk1 Primary Key,
DG_Username varchar(50),
DG_Password varchar(50),
DG_Contactno int ,
DG_StateNo int References DGState(DG_stateno))
Create table DGState
(DG_stateno Int Identity (1,1) NOT Null constraint pk Primary Key ,
DG_State varchar (50))
Now how can I create one stored procedure P which will enter values into DGRegion and DGState tables?
After click on submit I'm using asp.net.
Problem is: I can enter values into DGRegion table directly but how can I enter reference of state into table DGState?
Try something like this:
CREATE PROCEDURE dbo.EnterLoginData(#Username VARCHAR(50), #Password VARCHAR(50),
#ContactNo INT, #StateName VARCHAR(50))
AS BEGIN
DECLARE #StateID INT
-- check if state already exists
IF EXISTS(SELECT * FROM dbo.DGState WHERE DG_State = #StateName)
-- if it exists - retrieve the DG_StateNo
SELECT #StateID = DG_StateNo
FROM dbo.DGState
WHERE DG_State = #StateName
ELSE BEGIN
-- if it doesn't exists - insert new row
INSERT INTO dbo.DG_State(DG_State) VALUES(#StateName);
-- get the newly inserted row's ID using SCOPE_IDENTITY()
SELECT #StateID = SCOPE_IDENTITY()
END
INSERT INTO
dbo.DGRegion(DG_Username, DG_Password, DG_ContactID, DG_StateNo)
VALUES(#Username, #Password, #ContactNo, #StateID)
END
In the sp:
check if the state is in the state table
if not, put it into the state table
get the id (DG_stateno) of the state table, put in variable
execute your insert
I have a table with autoincremented primary key. In my code I am trying to receive the new autoincremented value when I execute each 'insert' query. Is there a way to do it programatically?
Thanks.
UPD:
Assume I have a table:
TABLE User ( userID INT NOT NULL AUTO_INCREMENT, name VARCHAR( 25 ) NOT NULL , email VARCHAR( 50 ) NOT NULL , UNIQUE ( userID ) );
And I when I insert new values (name and email) to this table I want automatically receive newly generated userID. Ideally I am looking for any ways to do that with a single transaction and without stored procedures.
Have your sql/stored proc return scope_identity() or if you are using Linq2SQL or EF the entity used for insertion gets the new id.
In the stored proc it is:
ALTER proc [dbo].[SaveBuild](
#ID int = 0 output,
#Name varchar(150)=null,
#StageID int,
#Status char(1)=null
)
as
SET NOCOUNT ON
Insert into Builds
(name, StageID, status)
values (#Name, #StageID, #Status)
select #ID = scope_identity()
RETURN #ID
In the C# code you have:
public int SaveBuild(ref int id, ref string Name)
{
SqlCommand cmd = GetNewCmd("dbo.SaveBuild");
cmd.Parameters.Add("#ID", SqlDbType.Int).Value = id;
cmd.Parameters["#ID"].Direction = ParameterDirection.InputOutput;
cmd.Parameters.Add("#Name", SqlDbType.VarChar).Value = Name;
cmd.Parameters.Add("#StageID", SqlDbType.Int).Value = 0;
ExecuteNonQuery(cmd);
id = (int)cmd.Parameters["#ID"].Value;
return id;
}
Dependent upon your situation, you might be better off using table-valued parameters to pass your inserts to a stored procedure, then use OUTPUT INSERTED to return a table-valued parameter from your stored procedure.
It will drastically reduce the number of hits required if you're processing multiple items.
Are you limited to building SQL on the client and sending it to the server? Cause if you can use a stored procedure, this is easy to do. In the stored proc, do the insert and then, either
Select Scope_Identity() as the last statement in the stored proc., or
Use a output parameter to the stored proc, (say named #NewPKValue) and make the last statement:
Set #NewPKValue = Scope_Identity()
Otherwise, you need to send a batch of commands to the server that include two statements, the insert, and Select Scope_Identity() and execute the batch as though it was a select statement
You could use the SQL statement SELECT scope_identity().