retrieve checkboxlist selection from database - asp.net

I have a checkboxlist which when submitted stores the selections in a table with the userid.The table is shown below :
Create table tblInterestByUserId
(
Id int primary key identity,
UserId varchar(10),
SubInterestId int,
SubInterest varchar(20),
InterestId int
)
Now i want to retrieve the selection on another checkboxlist on another page depending upon SubInterestId.I want to do something like this on the new page :
1.Going through all inserted SubInterest rows in tblInterestByUserId for the selected UserId.
2.Populating the checkboxlist according to the SubIinterest already present in tblInterestByUserId for that UserId
Please help me with a code-behind for the same on Page_Load.

Maybe a procedure to get the data you want....
CREATE PROCEDURE get_selections
#SubInterestId INT
AS
BEGIN
SET NOCOUNT ON;
SELECT SubInterest FROM tblInterestByUserId
WHERE SubInterestId = #SubInterestId
END
Call this procedure from the application code

My sugestion is tu use an enum with Flags in C# that maps with the subinterestID so then you can select the stored Ids and assign them to the enum.
see this:
http://forums.asp.net/t/1646982.aspx?enums+and+checkboxlist

Related

ASP.NET: Cannot insert duplicate key row in object

I have a index table to manage database on ASP.NET MVC. When I created new a product it ran out this error. What does that mean and how to fix it ?
Cannot insert duplicate key row in object 'Production.Product' with unique index 'AK_Product_rowguid'. The duplicate key value is (00000000-0000-0000-0000-000000000000).
You are missing a field in your insert. You should add something like this in your insert statement:
insert
into product
( ... -- other column names
, your_column_name
)
values
( ... -- other values
, newid()
)
00000000-0000-0000-0000-000000000000 is uniqueidentifier in sql or system.Guid in ASP. it has not been initialized yet, so i presume u are transmitting this value from ASP. Try adding a new parameter to your query with system.guid.newguid(), or system.guid.newguid.tostring if your query uses parameters.
If you are creating t-sql script to be exectued (ex: "insert into production.product values('"+TextBox1.Text+"', newid())" or "insert into production.product values('"+TextBox1.Text+"', '"+system.guid.newguid.tostring()+"')".
You can define for the uniqueidentifier column of product table a default value newid().

How can a computed column value be calculated and then inserted into database at runtime?

How can i write a insert query in my aspx page like following???
insert into tablname(field1 ,field2, field3)values(#field1,#field2,#field1-#field2)
Here I have made field3 a computed column in database as well which is field1 -field2 in database. Values inserted in fields are in textbox so i want at runtime to calculate difference two textboxes and then insert that value in database. How can i achieve this??
No need to include field 3 in your insert.
From MSDN: Unless otherwise specified, computed columns are virtual columns that are not physically stored in the table
So you can display the computed value on your form but when you do the actual insert into the database just insert the 2 values. The value for field3 will be computed when you query the table.
There are many ways but I would suggest you to create a stored procedure with two parameters #field1 and #field2 and perform the insert statement from there, like you can create a local variable within the stored procedure which will compute the value #field3 = #field1 - #field2 and submit the values (#field1, #field2, #field3)
create table test22(field1 int, field2 int, field3 int)
create proc inserttest22
#field1 int,
#field2 int
as
declare #field3 int
set #field3 = #field1 - #field2
insert into test22 values (#field1, #field2, #field3)
go

Updating data from GridView

I have a Gridview where I join two tables, bringing in the data to be displayed
table 1 sid, schedule, stime, splace, stourid
table 2 tourid, tourname
Basically they are joined stourid to tourid. That is so I can show the tourname in the grid.
Now I want to edit this GridView, what do I need to do, for instance, if the user edits the tourname, that it'll be saved to the database? I assume an Update statement is need, but how does it link to the GridView?
Whats the best and neatest method?
Regards,
Create Store Procedure to Update both tables and call it in your Update Code...
Create Proc UpdateData
#sid int,
#schedule,
#stime,
#splace,
#tourname
as
Begin
declare #tourid int,
select distinct #tourid=tourid from table1 where sid=#sid
begin try
// update tabel1
update tabel2 set tourname=#tourname where tourid =#tourid
end Try
begin Catch
end Catch
End
Using LinqToSQL you can do something like (if there is a FK relation between the tables)
DatabaseDataContext data = new DatabaseDataContext();
Table1 row = data.Table1s.Where(t =>t.ID == selectedID);
row.Table2.tourname = newName;
data.SubmitChanges();
You would then want to rebind the grid to show the new data.

The Link Between Webform Combobox Data and the Database (SQL Server & ASP.NET)

The title, while long, pretty much says it all.
What I have is a master table with a bunch of supporting table relations through foreign keys. For a few of the foreign tables, upon attempting to insert a record into the master table where one of the foreign keys doesn't exist, the data would be passed to the foreign table to create the record first, thereby making the constraint valid and passing the key to the created record back to the insert procedure of the master table.
This data comes from a form in String form, but naturally the foreign key will be an int. The process would look something like this:
-- ASP.NET Web Form --
Requestor Name: _____________ (combobox)
Request: _____________ (dropdownlist)
Date: _____________ (datepicker)
This is a super simplified version, but assume we have a master table with the above data, where both names are foreign keys to a People table. The name fields are comboboxes with a populated list of names linking to People. However, if I wanted to enter a person who didn't yet exist in the People table, the procedure should first create the Person, then use the ID from that new record as the foreign key in the Master table containing columns for the above.
I'm using SQL Server and ASP.NET with VB.NET codebehind. I've been scratching my head over this one for awhile, how to pass data (in different forms such as a foreign key or string) between the web server and DB server, as well as where to validate / transform the data.
It seems the entered name will be passed as an ID if the foreign key exists, and a String if not.
This is my most perplexing problem so far, and no idea where else to look. I've read up on Scott Mitchell's site and others.
MY SOLUTION (?)
The best I can come up with is to pass the user input from the user as a string and convert it to int in the T-SQL procedure. If the value was selected from the drop down, it should match precisely with a valid foreign key. If it doesn't match, then create a new Person and return a foreign key. Is this best practice?
This seems complicated because it is. You have to get your hands dirty. If you need a relational database with ACID support, there's no auto-magical way of getting around it.
Relational databases 101: The primary key must exist before the foreign key can be populated (This is the reason why data warehouse developers populate the dimension table before the fact table). You'll have to design the logic to validate that the primary key exists, insert and get the key if not, and just get the key if exists.
Here's my implementation. I don't know if it's the best, but it worked well for me. Basically I take the values from the controls; in the case of the combobox I need the values from both the TextBox and DropDownList. I then pass those values to the following function in my codebehind:
'This method determines if the name selected already exists in the selection
' options and if so assigns the corresponding ID value to an object variable,
' if not it assigns the value of the `TextBox` to the variable.
Protected Function _ValidateValues(ByRef ddl As DropDownList, ByRef cb As TextBox) As Object
'Ensures the selected value is valid by checking against the entered value in the textbox
If Not String.IsNullOrEmpty(cb.Text) Then
If ddl.Items.Count > 0 Then
If StrComp(cb.Text, ddl.SelectedItem.ToString) = 0 Then
Return ddl.Items.Item(ddl.SelectedIndex).Value 'Returns the index of dropdown selected name
End If
End If
'This counts the capital letters in the entered value and if fewer than 2
' auto capitalizes the first letters. This also allows for project code
' names such as "DOORS" and people names such as "Allen McPherson" etc.
' Be careful though because if "allen McPherson" is entered, it will NOT
' be corrected, though it displays correctly.
Dim rg As New Regex("[A-Z]")
Dim mc As MatchCollection = rg.Matches(cb.Text)
If mc.Count < 2 Then
Return StrConv(cb.Text, VbStrConv.ProperCase)
Else : Return cb.Text
End If
End If
'Returns a SQL DB NULL object if an empty string is submitted
Return DBNull.Value
End Function
Then my stored procedure handles the values something like so...
(Forgive me if I neglected to replace some of the values. I tried to catch them all.)
CREATE PROCEDURE spInsertUser
#User nvarchar(50) = NULL,
#Role nvarchar(50) = NULL,
#RecordID int output -- Returned Value
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- CHECK IF USER EXISTS
-- Insert new record to Users table if the requested user doesn't exist
-- Needed to ensure that the foreign keys are relevant
IF #User = '' OR #User IS NULL BEGIN SET #User = NULL SET #RecordID = NULL END --Ensures that an empty string cannot be submitted, thereby causing an error.
ELSE BEGIN
declare #forename varchar(50), #surname varchar(50)
declare #uid table (ID int)
declare #users table (ID smallint, Name nvarchar(50))
insert into #users
select ID, Name from Users
--If the value can be converted into an int, we need go no further.
BEGIN TRY SET #RecordID = CONVERT(smallint, #User) END TRY
BEGIN CATCH
BEGIN TRY --Otherwise, attempt to parse the name
Set #User = LTRIM(RTRIM(#User)) --Trim the extra space at the beginning and end. This ensures the following "IF" test will evaluate properly.
IF NOT CHARINDEX(' ', #User) > LEN(#User) AND CHARINDEX(' ', #User) > 0 BEGIN -- Confirm First & Last Name exist
Set #forename = RTRIM(LEFT(#User, CHARINDEX(' ',#User,0)-1))
Set #surname = LTRIM(RIGHT(#User, LEN(#User) - CHARINDEX(' ',#User,0)))
Set #User = #forename + ' ' + #surname --Ensure that there is a valid First & Last name
IF LEN(#forename) > 1 AND LEN(#surname) > 1 BEGIN -- Confirm First & Last Name exist
--First ensure that the User doesn't already exist, and if
-- so use their ID, if not insert the new User.
IF NOT EXISTS (select Name from #users where Name like #User) BEGIN --Check if the user already exists
INSERT INTO Users (Name, Forename, Surname) OUTPUT INSERTED.ID INTO #uid Values (#User, -- If not, insert them
#forename, #surname) --Nicely manicured first, last, and full names
SET #RecordID = CONVERT(smallint, (select MAX(ID) from #uid)) END -- Now set the Role to the ID of the new user
ELSE BEGIN --Otherwise if the user already exists, set the Role to the ID of that user
SET #RecordID = (select ID from #users where Name like #User) END
IF NOT EXISTS (select * from rUsersInRoles where UserID = #RecordID) BEGIN
--Do some string manipulation to increase the chances of matching the role
SET #Role = REPLACE(REPLACE(REPLACE(LTRIM(RTRIM(#Role)), ' ', '%'), '.', '%'), '#', '%') --Trims & replaces spaces & periods with wildcards
INSERT INTO rUsersInRoles (UserID, UserRoleID) VALUES
(#RecordID, (select top 1 ID from rUserRoles where Role like #Role)) END
END
END
END TRY
BEGIN CATCH END CATCH
END CATCH
END
END
This stored procedure deals with the case of User Roles as well. If the more simple case of Users only is needed, simply remove the clauses dealing with the checking and insertion of User Roles. :)

Numbering comments in ASP.NET and SQL Server

I've just thought about best way to store comments in database with appropriate numbers according to the article.
The idea is to store comments with composite primary key (commentId, articleId) where commentId is generated according to the given articleId. The system of generating should has same principle as IDENTITY generated columns in SQL Server, because if someone delete the comment, the number will be never used again. I guess there is not any functionality in Microsoft SQL Server to do that with composite PK, so I am asking about some replacement for this solution.
First thought was to use transaction to get MAX(commentId) + 1, but I am looking for something more abstract (maybe INSTEAD OF trigger), something that could be used for example in LINQ with no knowledge of the background, just insert to the appropriate table all required values (so no commentId) and save it.
I would use an autogenerated identity column for the commentId and have it be the primary key alone. I'd create an index on the articleId for look ups. I would also have createdDate column that is autopopulated with the current date on insertion -- mark it as db generated and readonly in LINQ so it doesn't require or try to insert/update the value. To get a numbering -- if showing them by date isn't enough -- I'd order by createdDate inversed and assign a numeric value in the select using Row_Number() or a numbering on the client side.
I would use an identity column as the key for the comments, why do you need a numbering for the comments stored in the database?
Thank you for responses, I wanted something with numbered comments because of referencing in the text of comments. I did not want to make reaction by names, sometimes one person reacts more times, so with this system, I will know to which one the person is replying.
So today I made up this INSTEAD OF INSERT trigger:
CREATE TRIGGER InsertComments ON Comments
INSTEAD OF INSERT
AS
DECLARE #Inserted TABLE
(
ArticleId INT NOT NULL,
UserId INT NOT NULL,
CommentDate DATETIME NOT NULL,
Content NVARCHAR(1000) NOT NULL,
RowNumber INT NOT NULL
)
INSERT INTO #Inserted
SELECT ArticleId, UserId, CommentDate, Content, ROW_NUMBER() OVER (ORDER BY CommentDate) AS RowNumber
FROM INSERTED
DECLARE #NumberOfRows INT = (SELECT COUNT(*) FROM #Inserted)
DECLARE #i INT = 1
WHILE (#i <= #NumberOfRows)
BEGIN
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
DECLARE #CommentId INT = (SELECT ISNULL(MAX(CommentId), 0)
FROM Comments WHERE ArticleId = (SELECT ArticleId
FROM #Inserted WHERE RowNumber = #i)) + 1
INSERT INTO Comments(CommentId, ArticleId, UserId, CommentDate, Content)
SELECT #CommentId, ArticleId, UserId, CommentDate, Content
FROM #Inserted WHERE RowNumber = #i
COMMIT
SET #i = #i + 1
END
I know this is not the perfect solution, but it works exactly how I needed. If any of you has some comments, I'll be happy to read them.

Resources