ObjectDataSource trouble - asp.net

I have been given a small project by the company I have applied for. They want a small application using asp.net GridView, FormView and an ObjectDataSource with a DataSet (xsd) file. I have been doing 3-tier applications but in a different way, I have my DataAccess layer as a c sharp file with methods accepting params and returning datatables etc. My business layer is another class with static methods returning business objects and collections making use of the DAL class. Now this ObjectDataSource is sth i did not really like, its generating some code that i can't even see where?
I could make the application work upto some point(90%). The other 10% is what my question about. I need to make a search by name functionality. There are two ObjectDataSources 1 and 2. ObjectDatasource1 just gets every record from the table on the first load. When search button cliked I set the datasource of gridview to the second ObjectDataSource which has a method called GetDataByNameSearch that is supposed to accept a parameter (all defined by wizzzardz) and parameter source is control (TextBox.Text). While my FormView works fine where it gets its parameter from QueryString, this search returns nothing. Search statement is as follows:
SELECT Birthday, CreatedAt, ID, Name, Surname
FROM Users
WHERE (Name LIKE '%#name%') OR
(Surname LIKE '%#name%')
Any idea about how these ObjectDataSources are supposed to be used, and make life easier(!)

Without code samples its hard to tell, but I did notice that your use of SQL parameters is a bit unusual.
You have:
SELECT Birthday, CreatedAt, ID, Name, Surname
FROM Users
WHERE (Name LIKE '%#name%') OR (Surname LIKE '%#name%')
I'm not sure if SQL '#' parameters will work when there are speechmarks around them. I think the above example will just result in the literal string '%#name%' being used in the query, which is why you might be getting no results.
SQL Parameters are usually used like this:
SELECT Birthday, CreatedAt, ID, Name, Surname
FROM Users
WHERE (Name LIKE #name) OR (Surname LIKE #name)
... but of course then you will lose the '%' wildcards. You might be able to add them directly into the parameter strings before they are passed to the query. If that is not possible, maybe try this version:
SELECT Birthday, CreatedAt, ID, Name, Surname
FROM Users
WHERE (Name LIKE '%' + #name + '%') OR (Surname LIKE '%' + #name + '%')

Related

Is it possible to select a field from a table, but override it with a new value in the select statement?

I am creating a view like this:
Let's say I originally have this:
select * from mydb.mytable
mydb.mytable has a field called FirstName, but I want to transform its value in the select statement. Conceptually, I want to do this:
select *, upper(firstname) firstname from mydb.mytable
The problem is that * is already returning FirstName, so adding another column of the same name to the select breaks the SQL. To get it to work, I have to list each field like this:
select upper(firstname) firstname, lastname, city, state, zip
This is just one example, but the table I really want to use this with has 30+ columns. I don't like the idea of having to list out each column because adding a new field to the table means I have to modify the SQL (ordinal field position doesn't matter).
Well, that's the way SQL is designed, it's not a specific Teradata problem.
You want something like "select * but firstname" and no DBMS has implemented such a syntax.
Btw, one of (my) basic SQL rules is: never write "SELECT *" :-)
As dnoeth says, that's just how SQL works. Also, I'd reinforce his comment about never using select *, especially in a view.
To address concerns like this, I keep the table and view DDL together in code. Whenever you change the table definition, you change the view definition at the same time. That way, whenever you add or remove columns from your table (your stated concern), your view always remains current.

Database schema advice for storing form fields and field values

I've been tasked with creating an application that allows users the ability to enter data into a web form that will be saved and then eventually used to populate pdf form fields.
I'm having trouble trying to think of a good way to store the field values in a database as the forms will be dynamic (based on pdf fields).
In the app itself I will pass data around in a hash table (fieldname, fieldvalue) but I don't know the best way to convert the hash to db values.
I'm using MS SQL server 2000 and asp.net webforms. Has anyone worked on something similar?
Have you considered using a document database here? This is just the sort of problem they solve alot better than traditional RDBMS solutions. Personally, I'm a big fan of RavenDb. Another pretty decent option is CouchDb. I'd avoid MongoDb as it really isn't a safe place for data in it's current implementation.
Even if you can't use a document database, you can make SQL pretend to be one by setting up your tables to have some metadata in traditional columns with a payload field that is serialized XML or json. This will let you search on metadata while staying out of EAV-land. EAV-land is a horrible place to be.
UPDATE
I'm not sure if a good guide exists, but the concept is pretty simple. The basic idea is to break out the parts you want to query on into "normal" columns in a table -- this lets you query in standard manners. When you find the record(s) you want, you can then grab the CLOB and deserialize it as appropriate. In your case you would have a table that looked something like:
SurveyAnswers
Id INT IDENTITY
FormId INT
SubmittedBy VARCHAR(255)
SubmittedAt DATETIME
FormData TEXT
A few protips:
a) use a text based serialization routine. Gives you a fighting chance to fix data errors and really helps debugging.
b) For SQL 2000, you might want to consider breaking the CLOB (TEXT field holding your payload data) into a separate table. Its been a long time since I used SQL 2000, but my recollection is using TEXT columns did bad things to tables.
The solution for what you're describing is called Entity Attribute Value (EAV) and this model can be a royal pain to deal with. So you should limit as much as possible your usage of this.
For example are there fields that are almost always in the forms (First Name, Last Name, Email etc) then you should put them in a table as fields.
The reason for this is because if you don't somebody sooner or later is going to realize that they have these names and emails and ask you to build this query
SELECT
Fname.value fname,
LName.Value lname,
email.Value email,
....
FROM
form f
INNER JOIN formFields fname
ON f.FormId = ff.FormID
and AttributeName = 'fname'
INNER JOIN formFields lname
ON f.FormId = ff.FormID
and AttributeName = 'lname'
INNER JOIN formFields email
ON f.FormId = ff.FormID
and AttributeName = 'email'
....
when you could have written this
SELECT
common.fname,
common.lname,
common.email,
....
FROM
form f
INNER JOIN common c
on f.FormId = c.FormId
Also get off of SQL 2000 as soon as you can because you're going to really miss the UNPIVOT clause
Its also probably not a bad idea to look at previous SO EAV questions to give you an idea of problems that people have encountered in the past
I'd suggest mirroring the same structure:
Form
-----
form_id
User
created
FormField
-------
formField_id
form_id
name
value

Need advice on ASP.NET localization - strings stored in a database & displayed in a gridview

I am looking for some advice on localization. I have an app that has been localized in the usual fashion (i.e., .resx files), which handles about 95% of the strings. However, I still need to localize some strings for category names that are stored in the database.
I'd like to avoid adding 15 new columns named categoryname_ES, categoryname_FR, etc, and then pulling the right column dynamically. If there would be some way to pull the data, and then do a substitution in the code, I think that would be a little less messy. Maybe along the lines of:
go through gridview row by row
if the language selected isn't english, look for this text value in a global resources file and replace it.
Anyone have a good idea of how to accomplish this? Or is adding a lot of categoryname columns for each language just the way to go (ewww).
I use the resource file method that you describe.
Add a CategoryName.resx file with a row for each category. Make sure the "Name" matches your database value exactly. Put the translation in the "Value".
Get the string in code via the resx's generated code file. (sorry for the C#)
Resources.CategoryName.ResourceManager.GetString(categoryName, new CultureInfo("fr"));
If you're binding to custom class, just make another property and bind to that property instead.
If you're binding to a DataSet, you might want to use the RowDataBound event to do the substitution.
You can do it with four database columns:
ID (unique primary key)
CultureCode
ProductID
ProductName
I presume that you are selecting your products from the database. Pass in the UI culture as part of the stored proc, then when you select from your product table join to the Culture table on the product ID and UICulture. You would phrase your SELECT something like this:
SELECT ProductID
,another field
,IsNull(Culture.ProductName, Product.ProductName)
,etc
FROM Product
LEFT JOIN Culture
ON Product.ProductID = Culture.ProductID
AND Culture.CultureCode = #UICulture
you get the idea. You could even check the UICulture for a hyphen (eg: fr-CA), split it into another variable, then do two joins to the Culture table - one for the exact culture, and one for the fallback culture, so in this example the first join would be for fr-CA and the second join would just fallback to fr. If all your culture joins fail (eg. because you don't have Zulu in the culture table), then the IsNull uses just the ordinary ProductName (which is probably in english).
You could create three tables:
Category
Category_ID (identity)
Category_Name (string)
Language
Language_ID (identity)
Language_Name (string)
CategoryLanguage
Category_ID (FK)
Language_ID (FK)
Translation (string)
The category table would have the names in English. The language table would have the languages that your application supports. The association table would then be able to provide the translated category name based on the selected language, if it exists. If it doesn't exist, then simply display the English version as the default.

SQL statement merging/simplifying

I'm not sure whether my SQL code and practise here is any good, so hopefully someone could enlighten me. In order to try and separate my DAL from the Business layer, I'm not using an SQLDataSource on the page. Instead, I've created a gridview to display the results and called an SQL command to retrieve results. I have the following SQL command:
string CommandText = "SELECT User.FName + User.Surname, Product.Name, Product.Quantity, Product.Price FROM User, Products WHERE Product.UserID = User.UserID";
The results are then loaded into a datareader and bound to the gridview control. This works fine. However, is the SQL statement inefficient? I've noticed some SQL statements have square brackets around each field, but when I try and put it around my fields, no results are displayed.
I'm also trying to merge the firstname and surname into one column, with a space between them, but the above doesn't put a space between them, and I can't seem to add a space in the SQL statement.
Finally, this all occurs in the code-behind of the shopping-cart page. However, is it insecure to have the connectionstring and above SQL statement in the codebehind? My connectionstring is encrypted within the web.config file and is called via the Configuration API.
Thanks for any help.
Firstly, using square brackets is optional in most cases (IIRC, there are very few instances where they are actually necessary, such as using keywords in the statement). Square brackets go around each identifier, for example,
SELECT [Server_Name].[Database_Name].[Table_Name].[Field_Name], ...
Secondly, to add a space, you can use SELECT User.FName + ' ' + User.Surname. You also might want to alias it - SELECT User.FName + ' ' + User.Surname AS [name]
Thirdly, keep the connection string in the web.config and encrypt it using a key.
Finally, you may want to consider introducing a data access layer into the project that can return objects from your datasource (might be worth having a look at NHibernate, LINQ to SQL or Entity Framework for this). You can then bind a collection of objects to your GridView.
Long time no SQL usage, but I don't see a problem with your query, as long as the database is designed well. To concatenate two string columns use something like this:
User.FName + ' ' + User.Surname AS UserName
Simply add a space between two strings.
As for security concerns: all other people can see is a rendered web page. If you don't expose connection string nor queries in the rendered HTML/JS code (like in comments etc.), you should not worry. The connection string stored in web.config and database structure visible in queries in server code are safe as long as the server is safe.
Try this:
string CommandText = "SELECT
User.FName + ' ' + User.Surname AS Fullname,
Product.Name,
Product.Quantity,
ProductDetail.Price
FROM
User, Products
WHERE
Product.UserID = User.UserID";
Best wishes,
Fabian

SQL - querying via a textbox which could take different values

Developing a website and just trying to get back into the swing of (clever) SQL queries etc, my mind had totally gone tonight!
There is a website http://www.ufindus.com/ which has a textbox allowing you to enter either a place name or a postcode/zipcode. I am trying to do something similiar but I am rubbish at SQL - so how do you construct an SQL statement that could potentially look at 2 columns (i.e. place and postcode) because you can't query both fields for the same value e.g
place = 'YORK' AND postcode = 'YORK'
or
place = 'YO21 5EA' AND postcode = 'YO21 5EA'
so do you have to put some logic in to be intelligent enough to detect whether it looks like a place name or a postcode - that just seems too complicated to me!! Any help would be much appreciated.
You could use an "OR" to get the job done. For example,
place = 'YORK' or postcode = 'YORK'
You might also do better using the LIKE statement, as in
WHERE place LIKE 'YORK%' or postcode LIKE 'YORK%'
(this assumes both place and postcode are character-based columns)
why not use OR instead of AND?
place = #textboxvalue OR post = #textboxvalue
What's wrong with attempting to match on the place and postcode? If I put in 'York' and (somewhere) that happens to be a valid postcode, I should get that result. As for preventing the same thing being entered twice, well, you can handle that on the validation prior to doing the database call.
Ah. Guess I was a bit slow on the up-take. Yes... what the others suggested is right, 'OR' is what you were looking for. I misinterpreted.
Ok, first I'm assuming that you have a table with a mapping of postcodes to placenames.
Let's call this table 'postcode' with columns 'postcode' and 'postplace'. Both of these are of a char-type.
Then.. whatever you do, make sure the input from the user is not part of dynamic sql. Make sure it is a parameter. Otherwise, you are inviting SQL injection attacks that can really ruin your day. This is important.
Our user input is in #textboxstring.
Given this, you can get the postcode and postplace like this:
select #textboxstring = RTRIM(#textboxstring) + '%';
select postcode, postplace
from postcode
where postcode like #textboxstring or postplace like #textboxstring;
Note that I'm modifying #textboxstring to get wildcard match with like without having to use dynamic sql.
If the postcode was integer, you would need to convert the input to int before executing the sql. So with a #textboxint as well, you could do this:
select #textboxstring = RTRIM(#textboxstring) + '%';
select postcode, postplace
from postcode
where postcode = #textboxint or postplace like #textboxstring;
Oh, and you need to handle that your search can have multiple results. You probably only want the first row.

Resources