DataTableMapping using adapter.FillSchema method applied on a Stored Procedure - asp.net

this is a method i was reading about #MSDN ,
my question is if for an example i would like to use it on a stored procedure
with the fact that the query of that stored procedure is already specifying columns to select from the table like following :
SELECT Columnsome, columnother, , , , ...FROM thisSQLdbTable
though i would like to implement the approach of that specific method , it seems very advanced from a little research i have made on
"the best way" available to extract data from SQL Server into Asp.net DataTable.
public static DataTable GetCustomerData(string dataSetName,
string connectionString)
{
DataTable table = new DataTable(dataSetName);
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlDataAdapter adapter = new SqlDataAdapter(
"SELECT CustomerID, CompanyName, ContactName FROM dbo.Customers", connection);
DataTableMapping mapping = adapter.TableMappings.Add("Table", "Customers");
mapping.ColumnMappings.Add("CompanyName", "Name");
mapping.ColumnMappings.Add("ContactName", "Contact");
connection.Open();
adapter.FillSchema(table, SchemaType.Mapped);
adapter.Fill(table);
return table;
}
}
or is it not the method to use if i am querying via SP that specifies the selected column
i could actually drop that stored procedure if it is not requiered to select /specify columns
the stored procedure is doing a specific calculation and updates the table with results of calculation then i am switching it's "MODE" to select results from the table that was updated.
what i did is recyceling (; giving it a parameter (bit type)
stored procedure then asks for the value of supplied bool / bit Parameter,
if its is status true it updates (doing its original task it was made for)
if its false its doing a select oporation so i am using it as i would with 2 separated commands
but now that i have search for a better way to extract data from db into a Data table
i give up on the two way SP and i will make a selection via the exaple above if they're not intended to be used thogether as with my current SP that does preselection when servs the GetCustomersData() above.
So the question is do i need to let the function to make the selection or can i serve it with my sp ready made selection to implemet it with GetCustomersData() in the way that it will only do rest of task and only mapp the columns that was preselected

Still a bit confused on your actual requirement but here goes:
I See you are using a direct query in your C# code, 'best way' would be to make a SP out of it then say:
SqlCommand command = conn.CreateCommand();
SqlDataAdapter sqlAdapter = new SqlDataAdapter(command);
command.CommandType = System.Data.CommandType.StoredProcedure;
command.CommandText = "sp_GetCustomerData";
Then after you have added parameters if needed do:
conn.Open();
sqlAdapter.Fill(dtResult);
conn.Close();
Where dtResult is Datatable.
So you do not need to do any mapping in this case, and since you are using a SP from the Database it will work faster than your direct query and you can change the query logic any time without the need of re deploying your code.

Stored procedures are perfectly valid in this use case. however, if you want more of a properly mapped table, you have several options, some of which go beyond the use of DataTables.
You can use strongly typed DataSets or perhaps use an ORM (object relational mapper).
ref: Typed Datasets: http://msdn.microsoft.com/en-us/library/esbykkzb(v=vs.71).aspx
ref: What is an ORM : http://en.wikipedia.org/wiki/Object-relational_mapping
EXAMPLES OF ORM'S
ref: Entity Framework : http://msdn.microsoft.com/en-us/data/ef.aspx
ref: NHibernate: http://nhforge.org/

Related

Azure Elastic Scale Sharding Key

I am moving my datamodel to Azure Elastic Scale.
After some testing and some experiences I fall in love if it, it is simple and with that kind of approach the code remains clean and easy to maintain.
I just have one big question, where is the Sharding key defined? I cannot find info on the sample downloaded from Visual Studio and I can beat that this is a straight forward answer.
In the sample offered by Microsoft the default sharding key is CustomerId but i cannot find where the reference to that key takes place.
Could it be in ShardMapName from configuration file?
Thanks in advance.
There is no explicit link between the the sharding key in the SQL schema and its usage (in code).
So in the Getting Started sample, the Customers and Orders table both contain a CustomerId column, and you can see that in DataDependentRoutingSample.cs when we access these tables we make sure to provide the same customerId value to the shardMap.OpenConnectionForKey method that we then use for customerId column (both in the SELECT and INSERT statements) in the following query.
// Looks up the key in the shard map and opens a connection to the shard
using (SqlConnection conn = shardMap.OpenConnectionForKey(customerId, credentialsConnectionString))
{
// Create a simple command that will insert or update the customer information
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = #"
IF EXISTS (SELECT 1 FROM Customers WHERE CustomerId = #customerId)
UPDATE Customers
SET Name = #name, RegionId = #regionId
WHERE CustomerId = #customerId
ELSE
INSERT INTO Customers (CustomerId, Name, RegionId)
VALUES (#customerId, #name, #regionId)";
cmd.Parameters.AddWithValue("#customerId", customerId);
cmd.Parameters.AddWithValue("#name", name);
cmd.Parameters.AddWithValue("#regionId", regionId);
cmd.CommandTimeout = 60;
// Execute the command
cmd.ExecuteNonQuery();
}
In other words, when you provide a certain key value in the OpenConnectionForKey call, it's your responsibility to make sure that all SQL queries with that connection are restricted to that key value, otherwise you may end up with incorrect results (e.g. if it was a SELECT query) or rows living on the wrong shard (e.g. if it was an INSERT query).
It's possible to fix this safety issue by using the new Row-Level Security feature. We have a sample called Entity Framework Multi-Tenant Shards that demonstrates how to combine Shard Maps with Row-Level Security. The relevant code is in ElasticScaleContext.cs:
SqlConnection conn = null;
try
{
// Ask shard map to broker a validated connection for the given key
conn = shardMap.OpenConnectionForKey(shardingKey, connectionStr, ConnectionOptions.Validate);
// Set CONTEXT_INFO to shardingKey to enable Row-Level Security filtering
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = #"SET CONTEXT_INFO #shardingKey";
cmd.Parameters.AddWithValue("#shardingKey", shardingKey);
cmd.ExecuteNonQuery();
return conn;
}
catch (Exception)
{
if (conn != null)
{
conn.Dispose();
}
throw;
}
Thanks for your great question!

Use SQL IN inside vb.net dataset adaptor

I'm trying to use a dataset adapter in my asp.net/vb.net website. But I need to search using multiple values, Ideally, i'd just like to pass an in statement in to my dataset adapter. Is this possible, as how it is, it doesn't seem to bring back anything:
Heres my data adapter:
The query is:
select * from joblist where username in (#username)
I'm trying to call it with:
Private dtJobs As Barry.joblistDataTable
Private taJobs As New BarryTableAdapters.joblistTableAdapter
dtJobs = New Barry.joblistDataTable
dtJobs = taJobs.FilterSearch("'tomb','martinm','chrise'")
rptJobList.DataSource = dtJobs
rptJobList.DataBind()
What am I doing wrong?
You're passing in a comma separated string, a single parameter. You cannot use it as is in an IN statement.
You have to split it into table, for example using this solution. Using this function (I assume you're using SQL Server as your DB) you can rewrite your query as:
select joblist.* from joblist
inner join dbo.Split(',', #username) t
on joblist.username = t.s
This approach splits your multi-value parameter into table and joins to the original table

ASP.NET page can Insert a date to an Access database, but not Update

I have an ASP.NET page that needs to push a little data to an MS Access 2003 database. The process requires a Select on one record, Inserting one new record and Updating one record. I am connecting to the Access database via an OleDbConnection connection. So far, the Select and Insert functions are working exactly as expected (so I know my connection is good). The Update, however, fails to update any rows. The function to update the record looks like this:
public static int UpdateDeviceDates(int deviceId, DateTime nextTestDate)
{
var conn = DbConnect.AccessConnection();
var sqlString = WebConfigurationManager.AppSettings["UpdateDeviceDates"];
using (var cmd = new OleDbCommand(sqlString, conn))
{
cmd.Parameters.AddWithValue("#DeviceID", deviceId);
cmd.Parameters.AddWithValue("#NextTestDate", nextTestDate);
cmd.CommandType = CommandType.Text;
conn.Open();
var result = cmd.ExecuteNonQuery();
return result;
}
}
The sqlString pulled back from the web.config file looks like this:
UPDATE tblDevice
SET tblDevice.NextTestDate = #nextTestDate,
tblDevice.FirstNoticeDate = Null,
tblDevice.SecondNoticeDate = Null
WHERE DeviceID=#deviceId;
This query works fine if you paste it into a new Access query window and hit run, so I know the syntax is correct. I have done quite a bit of testing and figured out that it is the #nextTestDate field that is causing it to fail. When I took that out of the SQL string, it updated the record as expected. This is disconcerting, because the date I pass through to the Insert function works just fine.
I have looked around quite a bit and the closest I found to an answer was "Can't update date in aspx to a MS-ACCESS table". The main answer there was to change the parameter to a ShortDateString. I tried that to no effect. It was also suggested to bracket the date in #, since that is what Access does in its own queries. Unfortunately, that didn't work either.
I don't know why either of these should have been necessary, because the date comes through in exactly the same format as in the Insert statement and that works fine. I'm at my wits end here because the only thing I've found to make that query work is to remove the date parameter (which would defeat the main purpose of the query).
In your query, the parameters are in a different order, the order must match:
cmd.Parameters.AddWithValue("#NextTestDate", nextTestDate);
cmd.Parameters.AddWithValue("#DeviceID", deviceId);
To match:
UPDATE tblDevice
SET tblDevice.NextTestDate = #nextTestDate, <--- Param 1
tblDevice.FirstNoticeDate = Null,
tblDevice.SecondNoticeDate = Null
WHERE DeviceID=#deviceId; <--- Param 2

Entity Framework Update Time & Date Column with Parameterized

I have changed all my code from the raw ADO.NET SQLCommand to Entity Framework in order to have easier accessibility of changing my code in the future. However, I have realized there are many drawbacks in Entity Framework it is not as simple as injecting raw SQL commands into the database. Moreover, I have used Reverse Engineering to generate the Models & Mapping for MS Sql Server.
Currently, I am trying to do the following but none of the columns are getting updated.
string sql = #"UPDATE [ProductDB] SET CreatedProduct_Time=getdate(), CreatedProduct_Date=getdate()" + " WHERE [Material_No] = #Material_No";
db.Database.ExecuteSqlCommand(sql, new SqlParameter("#Material_No", materialnotxt));
The columns are not getting updated.
I am having a doubt whether Entity Framework will help me maintain my code for future use and is it worth the headache using it instead of the old raw SQL code? So far there are many constraints and it requires a higher learning curve.
Some confusing parts I have find online what is the difference between the context.Database.ExecuteSqlCommand and this MSDN http://msdn.microsoft.com/en-us/library/bb738684.aspx the code looks entirely different then my approach.
EDIT
I have used a different approach to insert the Date and Time while inserting all the info from the textbox.
using (var db = new ROGContext())
{
ProductDB product = new ProductDB
{
Material_No = long.Parse(MaterialNo_txtbox.Text),
Product_Line = ProductLineDropDownList1.SelectedItem.Text,
Product_Description = Description_txtbox.Text,
Size = Size_txtbox.Text,
UOM = UOM_txtbox.Text,
SupplierID = long.Parse(SupplierCountryListBox.SelectedItem.Value),
CreatedProduct_Date = DateTime.Parse(System.DateTime.Now.ToShortDateString()), //in the SQL database I have set the datatype as date to get yyyy/mm/dd
CreatedProduct_Time = DateTime.Now.TimeOfDay //in the SQL database I have set the datatype as time(0) to get hh:mm:ss
};
long queryselect = (from materialno in db.ProductDBs
where materialno.Material_No == product.Material_No
select materialno.Material_No).SingleOrDefault();
if (queryselect != long.Parse(materialnotxt))
{
Label1.Text = "Product successfully added in database";
Label1.Visible = true;
db.ProductDBs.Add(product);
db.SaveChanges();
}
You can use Context.ExecuteStoreCommand for Insert, Update and Delete.
See in Page 64 of Entity Framework 4.0 Recipes: A Problem-Solution Approach
Answer your edited part:
ExecuteStoreQuery for Select
ExecuteStoreCommand for Insert, Update and Delete
Entity Framework v4 – Tips and Tricks

SQLite Parameters - Not allowing tablename as parameter

I'm developing an application in AIR via Flex, but I'm not seeing where I'm going wrong with SQLite (I'm used to MySQL). Parameters work, but only in certain instances. Is this part of the built-in sanitation system against sql injection? Thanks for any help!
Works:
sqlite
"INSERT :Fields FROM Category", where the parameter is :Fields = "*"
as3
var statement:SQLStatement = new SQLStatement();
statement.connection = connection;
statement.text = "INSERT :Fields FROM Category";
statement.parameters[":Fields"] = "*";
statement.execute;
Doesn't Work (SQL syntax error at ":Table"):
sqlite
"INSERT :Fields FROM :Table", where the parameters are :Fields = "*" and :Table = "Category"
as3
var statement:SQLStatement = new SQLStatement();
statement.connection = connection;
statement.text = "INSERT :Fields FROM :Table";
statement.parameters[":Fields"] = "*";
statement.parameters[":Table"] = "Category";
statement.execute;
Generally one cannot use SQL parameters/placeholders for database identifiers (tables, columns, views, schemas, etc.) or database functions (e.g., CURRENT_DATE), but instead only for binding literal values.
With server-side support for parameterized (a.k.a. prepared) statements, the DB engine parses your query once, remembering out the peculiars of any parameters -- their types, max lengths, precisions, etc. -- that you will bind in subsequent executions of the already-parsed query. But the query cannot be properly parsed into its syntactic elements if critical bits, like database objects, are unknown.
So, one generally has to substitute table names oneself, in a stored procedure or in client code which dynamically concats/interpolates/whatevers the SQL statement to be properly executed. In any case, please remember to use your SQL API's function for quoting database identifiers, since the API won't do it for you.
Not sure if this is the same but I ran across something similar in Java. Basically you can't add a table as a parameter so you must generate the statement like so:
var statement:SQLStatement = new SQLStatement();
statement.connection = connection;
statement.text = stringUtil.substitute("INSERT :Fields FROM {0}", "Category");
statement.parameters[":Fields"] = "*";
statement.execute;
This is mostly likely not the securest solution, so you might want to some custom validation of the data before you add the table name.. so someone doesn't try to send it the table name ";drop tableName..."

Resources