Can I execute multiple queries and return their results executing a SqlCommand just once?
See SqlDataReader.NextResult (an SqlDataReader is returned from calling SqlCommand.ExecuteReader):
Advances the data reader to the next result [set], when reading the results of batch Transact-SQL statements.
Example:
string commandText = #"SELECT Id, ContactId
FROM dbo.Subscriptions;
SELECT Id, [Name]
FROM dbo.Contacts;";
List<Subscription> subscriptions = new List<Subscription>();
List<Contact> contacts = new List<Contact>();
using (SqlConnection dbConnection = new SqlConnection(#"Data Source=server;Database=database;Integrated Security=true;"))
{
dbConnection.Open();
using (SqlCommand dbCommand = dbConnection.CreateCommand())
{
dbCommand.CommandText = commandText;
using(SqlDataReader reader = dbCommand.ExecuteReader())
{
while(reader.Read())
{
subscriptions.Add(new Subscription()
{
Id = (int)reader["Id"],
ContactId = (int)reader["ContactId"]
});
}
// this advances to the next resultset
reader.NextResult();
while(reader.Read())
{
contacts.Add(new Contact()
{
Id = (int)reader["Id"],
Name = (string)reader["Name"]
});
}
}
}
}
Other examples:
C# Multiple Result Sets
Executing a Query That Returns Multiple Result Sets with SqlDataReader : SqlCommand Select « ADO.Net « C# / CSharp Tutorial
Create a Stored Procedure that has multiple selects, and fill the DataSet.
using (SqlConnection conn = new SqlConnection(connection))
{
DataSet dataset = new DataSet();
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = new SqlCommand("MyProcedure", conn);
adapter.SelectCommand.CommandType = CommandType.StoredProcedure;
adapter.Fill(dataset);
return dataset;
}
The returned dataset will have a DataTable in it's Tables array for each select in the stored procedure.
Tools like "dapper" make this very easy, regardless of whether you use ad-hoc text queries or stored procedures; for example:
using(var multi = conn.QueryMultiple(sql, args))
{
var customers = multi.Read<Customer>().AsList(); // first grid
var regionName = multi.ReadFirstOrDefault<string>(); // second grid
var addresses = multi.Read<Address>().AsList(); // third grid
// todo: use those things
}
Individual grids can also be read without buffering (as an open IEnumerable<T> over the reader itself) via the optional parameters to Read[<T>].
I am using a dictionary approach.
You can use Newton Json to convert it to json.
This way you are not tied to types and IDataRecord
public List<List<Dictionary<string, object>>> ExecuteSqlReader(string cmd, int commandTimeout = 30, CommandType commandType = CommandType.Text)
{
var sqlCmd = new SqlCommand(cmd);
var allRecord = new List<List<Dictionary<string, object>>>();
using (var connection = GetSqlConnection(commandTimeout, commandType, ref sqlCmd))
{
using (var reader = sqlCmd.ExecuteReader())
{
if (reader.HasRows)
{
var result = new List<Dictionary<string, object>>();
while (reader.Read())
{
result = GetTableRowData(reader);
}
allRecord.Add(result);
}
while (reader.NextResult())
{
if (reader.HasRows)
{
var result = new List<Dictionary<string, object>>();
while (reader.Read())
{
result = GetTableRowData(reader);
}
allRecord.Add(result);
}
}
}
}
return allRecord;
}
I call a sproc and get multiple result sets with object, so you end up with a
List<List<Dictionary<string, object>>>
In the multiResultsSet each results set is then
List<Dictionary<string, object>>
They can be cast to their types and transformed into the models as needed.
After you set up the sproc command with everything needed, pass it to this:
private static List<List<Dictionary<string, object>>> ProcessReader(SqlCommand command)
{
var tables = new List<List<Dictionary<string, object>>>();
using (var reader = command.ExecuteReader())
{
do
{
var table = new List<Dictionary<string, object>>();
while (reader.Read())
table.Add(Read(reader));
tables.Add(table);
} while (reader.NextResult());
}
return tables;
}
and Read() is fairly straight forward.
private static Dictionary<string, object> Read(IDataRecord reader)
{
var row = new Dictionary<string, object>();
for (var i = 0; i < reader.FieldCount; i++)
{
var val = reader[i];
row[reader.GetName(i)] = val == DBNull.Value ? null : val;
}
return row;
}
This is what i have been using for returning multiple result sets.
public abstract class BaseRepo
{
private string _connectionString;
protected BaseRepo(string connectionString)
{
_connectionString = connectionString;
}
private SqlConnection GetSqlConnection(int commandTimeout, CommandType commandType, ref SqlCommand sqlCmd)
{
var connection = new SqlConnection(_connectionString);
connection.Open();
sqlCmd.Connection = connection;
sqlCmd.CommandTimeout = commandTimeout;
sqlCmd.CommandType = commandType;
return connection;
}
protected int ExecuteSql(SqlCommand sqlCmd, int commandTimeout = 30, CommandType commandType = CommandType.Text)
{
using (var connection = GetSqlConnection(commandTimeout, commandType, ref sqlCmd))
{
return sqlCmd.ExecuteNonQuery();
}
}
protected IEnumerable<T> ExecuteSqlReader<T>(Func<IDataRecord, T> CreateObject, SqlCommand sqlCmd, int commandTimeout = 30, CommandType commandType = CommandType.Text)
{
using (var connection = GetSqlConnection(commandTimeout, commandType, ref sqlCmd))
{
using (var reader = sqlCmd.ExecuteReader())
return ExecuteReader(CreateObject, reader);
}
}
protected Tuple<IEnumerable<T1>, IEnumerable<T2>> ExecuteSqlReader<T1,T2>(Func<IDataRecord, T1> CreateObject1, Func<IDataRecord, T2> CreateObject2, SqlCommand sqlCmd, int commandTimeout = 30, CommandType commandType = CommandType.Text)
{
using (var connection = GetSqlConnection(commandTimeout, commandType, ref sqlCmd))
{
using (var reader = sqlCmd.ExecuteReader())
{
var result1 = ExecuteReader(CreateObject1, reader).ToList();
var result2 = ExecuteReader(CreateObject2, reader).ToList();
return Tuple.Create<IEnumerable<T1>, IEnumerable<T2>>(result1, result2);
}
}
}
protected Tuple<IEnumerable<T1>, IEnumerable<T2>, IEnumerable<T3>> ExecuteSqlReader<T1, T2, T3>(Func<IDataRecord, T1> CreateObject1, Func<IDataRecord, T2> CreateObject2, Func<IDataRecord, T3> CreateObject3, SqlCommand sqlCmd, int commandTimeout = 30, CommandType commandType = CommandType.Text)
{
using (var connection = GetSqlConnection(commandTimeout, commandType, ref sqlCmd))
{
using (var reader = sqlCmd.ExecuteReader())
{
var result1 = ExecuteReader(CreateObject1, reader).ToList();
var result2 = ExecuteReader(CreateObject2, reader).ToList();
var result3 = ExecuteReader(CreateObject3, reader).ToList();
return Tuple.Create<IEnumerable<T1>, IEnumerable<T2>, IEnumerable<T3>>(result1, result2, result3);
}
}
}
protected Tuple<IEnumerable<T1>, IEnumerable<T2>, IEnumerable<T3>, IEnumerable<T4>> ExecuteSqlReader<T1, T2, T3, T4>(Func<IDataRecord, T1> CreateObject1, Func<IDataRecord, T2> CreateObject2, Func<IDataRecord, T3> CreateObject3, Func<IDataRecord, T4> CreateObject4, SqlCommand sqlCmd, int commandTimeout = 30, CommandType commandType = CommandType.Text)
{
using (var connection = GetSqlConnection(commandTimeout, commandType, ref sqlCmd))
{
using (var reader = sqlCmd.ExecuteReader())
{
var result1 = ExecuteReader(CreateObject1, reader).ToList();
var result2 = ExecuteReader(CreateObject2, reader).ToList();
var result3 = ExecuteReader(CreateObject3, reader).ToList();
var result4 = ExecuteReader(CreateObject4, reader).ToList();
return Tuple.Create<IEnumerable<T1>, IEnumerable<T2>, IEnumerable<T3>, IEnumerable<T4>>(result1, result2, result3, result4);
}
}
}
private IEnumerable<T> ExecuteReader<T>(Func<IDataRecord, T> CreateObject, SqlDataReader reader)
{
while (reader.Read())
{
yield return CreateObject(reader);
}
reader.NextResult();
}
}
Then I just inherit it like so:
public class ReviewRepo : BaseRepo
{
public ReviewRepo(string connectionString) : base(connectionString) { }
public ReviewPageableResult GetAllReviews(string productType, string serviceType, int pageNumber, int itemsPerPage, string sortBy, string sortDirection)
{
var parameters = new List<SqlParameter>
{
new SqlParameter("ProductRefDescription", productType),
new SqlParameter("ServiceRefDescription", serviceType),
new SqlParameter("ZipCodes", "NULL"),
new SqlParameter("PageNumber", pageNumber),
new SqlParameter("ItemsPerPage", itemsPerPage),
new SqlParameter("SortBy", sortBy),
new SqlParameter("SortDirection", sortDirection)
};
var cmd = new SqlCommand("dbo.GetReviews");
cmd.Parameters.AddRange(parameters.ToArray());
var results = ExecuteSqlReader(CreateReview, CreateReviewPageableResult, cmd, commandType: CommandType.StoredProcedure);
var reviewResult = results.Item2.Single();
reviewResult.Items = results.Item1;
return reviewResult;
}
public ReviewPageableResult GetReviewsByZip(string productType, string serviceType, string zipCodes, int pageNumber, int itemsPerPage, string sortBy, string sortDirection)
{
var parameters = new List<SqlParameter>
{
new SqlParameter("ProductRefDescription", productType),
new SqlParameter("ServiceRefDescription", serviceType),
new SqlParameter("ZipCodes", zipCodes),
new SqlParameter("PageNumber", pageNumber),
new SqlParameter("ItemsPerPage", itemsPerPage),
new SqlParameter("SortBy", sortBy),
new SqlParameter("SortDirection", sortDirection)
};
var cmd = new SqlCommand("dbo.GetReviewsByZipCodes");
cmd.Parameters.AddRange(parameters.ToArray());
var results = ExecuteSqlReader(CreateReview, CreateReviewPageableResult, cmd, commandType: CommandType.StoredProcedure);
var reviewResult = results.Item2.Single();
reviewResult.Items = results.Item1;
return reviewResult;
}
private Review CreateReview(IDataRecord record)
{
return new Review
{
PageReviewId = (int)record["PageReviewId"],
ProductRefId = (Guid)record["ProductRefId"],
ServiceTypeRefId = Convert.IsDBNull(record["ServiceTypeRefId"]) ? Guid.Empty : (Guid)record["ServiceTypeRefId"],
TerritoryId = Convert.IsDBNull(record["TerritoryId"]) ? Guid.Empty : (Guid)record["TerritoryId"],
FirstName = $"{record["FirstName"]}",
LastName = $"{record["LastName"]}",
City = $"{record["City"]}",
State = $"{record["State"]}",
Answer = $"{record["Answer"]}",
Rating =(double)record["Rating"],
SurveyDate = (DateTime)record["SurveyDate"]
};
}
private ReviewPageableResult CreateReviewPageableResult(IDataRecord record)
{
return new ReviewPageableResult
{
AverageRating = (double)record["AverageRating"],
Count1Stars = (int)record["Count1Stars"],
Count2Stars = (int)record["Count2Stars"],
Count3Stars = (int)record["Count3Stars"],
Count4Stars = (int)record["Count4Stars"],
Count5Stars = (int)record["Count5Stars"],
ItemsPerPage = (int)record["ItemsPerPage"],
PageNumber = (int)record["PageNumber"],
TotalCount = (int)record["TotalCount"],
};
}
}
Try this
Dim dt1, dt2, dt3As New DataTable
Dim command As SqlCommand
Dim adapter As New SqlDataAdapter
Dim ds As New DataSet
Dim Sql1, Sql2, Sql3 As String
Sql1 = "select id, CurName from Table1 where IS_Deleted=0 order by id"
Sql2 = "select id ,Item from Table2 order by id"
Sql3 = "select id ,SellPrice from Table3 order by id"
Try
conn1.Open()
command = New SqlCommand(Sql1, conn1)
command.CommandType = CommandType.Text
adapter.SelectCommand = command
adapter.Fill(ds, "dt1")
adapter.SelectCommand.CommandText = Sql2
adapter.Fill(ds, "dt2")
adapter.SelectCommand.CommandText = Sql3
adapter.Fill(ds, "dt3")
adapter.Dispose()
command.Dispose()
conn1.Close()
cmbCurrency.DataSource = ds.Tables("dt1")
cmbCurrency.DisplayMember = "CurName"
cmbCurrency.ValueMember = "id"
cmbCurrency.SelectedIndex = -1
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''|
cmbGroups.DataSource = ds.Tables("dt2")
cmbGroups.DisplayMember = "Item"
cmbGroups.ValueMember = "id"
cmbGroups.SelectedIndex = -1
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''|
cmbUnits.DataSource = ds.Tables("dt3")
cmbUnits.DisplayMember = "SellPrice"
cmbUnits.ValueMember = "id"
cmbUnits.SelectedIndex = -1
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''|
Catch ex As Exception
MessageBox.Show(ex.ToString())
End Try
For More Help http://vb.net-informations.com/dataset/dataset-multiple-tables-sqlserver.htm
This method retrieves the entire data.
I'm trying to switch this method to a method that uses a dictionary but it doesn't work very well.
INSERT, UPDATE, and DELETE completed but I'm having trouble with SELECT.
I want convert to the my method like below link source.
https://gist.github.com/thorsman99/e788dd9cce36c26edd9076c9dac288dd
public static List<TestModel> GetList(string id, string subject, string UseYN, string createDate1, string createDate2)
{
using(SQLiteConnection connection = new SQLiteConnection(_connection))
{
connection.Open();
using(SQLiteCommand command = new SQLiteCommand(connection))
{
command.CommandText = #"SELECT ID, Subject, CreateDate, UpdateDate FROM Test";
command.Parameters.Add(new SQLiteParameter(#"ID" , DbType.String) { Value = id });
command.Parameters.Add(new SQLiteParameter(#"Subject" , DbType.String) { Value = subject });
command.Parameters.Add(new SQLiteParameter(#"CreateDate1", DbType.String) { Value = createDate1 });
command.Parameters.Add(new SQLiteParameter(#"CreateDate2", DbType.String) { Value = createDate2 });
SQLiteDataReader reader = command.ExecuteReader();
List<TestModel> list = new List<TestModel>();
while(reader.Read())
{
TestModel item = new TestModel();
item.ID = reader["ID" ].ToString();
item.Subject = reader["Subject" ].ToString();
item.CreateDate = Convert.ToDateTime(reader["CreateDate"]);
item.UpdateDate = Convert.ToDateTime(reader["UpdateDate"]);
list.Add(item);
}
return list;
}
}
}
I moved connection.Open to directly before the.ExecuteReader` Connections should be open for the shortest possible time. I moved the declare of the Dictionary outside the using block and then the return outside also. This again is to close the connection as soon as possible.
I combined the 2 using blocks to one. Just simplifies the code a bit and saves indenting.
For the dictionary, I used "ID" as the key. I assumed that this was the Primary Key and therefore unique.
public Dictionary<string, TestModel> GetTestModelDictionary(string id, string subject, string UseYN, string createDate1, string createDate2)
{
Dictionary<string, TestModel> dict = new Dictionary<string, TestModel>();
using (SQLiteConnection connection = new SQLiteConnection(_connection))
using (SQLiteCommand command = new SQLiteCommand(connection))
{
command.CommandText = #"SELECT ID, Subject, CreateDate, UpdateDate FROM Test";
command.Parameters.Add(new SQLiteParameter(#"ID", DbType.String) { Value = id });
command.Parameters.Add(new SQLiteParameter(#"Subject", DbType.String) { Value = subject });
command.Parameters.Add(new SQLiteParameter(#"CreateDate1", DbType.String) { Value = createDate1 });
command.Parameters.Add(new SQLiteParameter(#"CreateDate2", DbType.String) { Value = createDate2 });
connection.Open();
SQLiteDataReader reader = command.ExecuteReader();
while (reader.Read())
{
TestModel item = new TestModel();
item.ID = reader["ID"].ToString();
item.Subject = reader["Subject"].ToString();
item.CreateDate = Convert.ToDateTime(reader["CreateDate"]);
item.UpdateDate = Convert.ToDateTime(reader["UpdateDate"]);
dict.Add(item.ID, item);
}
}
return dict;
}
I have this method:
public class StoredProcedureProvider : IStoredProcedureProvider
{
private readonly string _connectionString;
public StoredProcedureProvider(IDataConfig config) => _connectionString = config.ConnectionString;
public T ExecuteScalar<T>(string procedureName, IList<SqlParameter> parameters = null)
{
return Execute(procedureName, parameters, (connection, command) =>
{
connection.Open();
var result = command.ExecuteScalar();
return (T) Convert.ChangeType(result, typeof(T));
});
}
public DataSet GetDataSet(string procedureName, IList<SqlParameter> parameters = null)
{
return Execute(procedureName, parameters, (connection, command) =>
{
var dataAdapter = new SqlDataAdapter();
var dataSet = new DataSet();
dataAdapter.SelectCommand = command;
dataAdapter.Fill(dataSet);
return dataSet;
});
}
public DataRow GetDataRow(string procedureName, IList<SqlParameter> parameters = null)
{
var dataSet = GetDataSet(procedureName, parameters);
var tables = dataSet.Tables.Cast<DataTable>().ToList();
if (!tables.Any())
throw new Exception("The DataSet contains not tables");
var dataRows = dataSet.Tables[0].Rows.Cast<DataRow>().ToList();
if (!dataRows.Any())
throw new Exception("The DataTable contains no rows");
var dataRow = dataRows.First();
return dataRow;
}
private static T Execute<T>(string procedureName, IList<SqlParameter> parameters, Func<SqlConnection, SqlCommand, T> returnMethod)
{
using (var connection = new SqlConnection(_connectionString))
{
using (var command = new SqlCommand(procedureName, connection))
{
command.CommandType = CommandType.StoredProcedure;
if (parameters == null || !parameters.Any())
return returnMethod(connection, command);
foreach (var parameter in parameters)
command.Parameters.Add(parameter);
return returnMethod(connection, command);
}
}
}
}
When I invoke anything with a parameter that is not a string, I get an error:
Procedure or function 'generalLogonFromSessionID' expects parameter '#sessionID', which was not supplied.
The code I am using to test this is:
var dataRow = _storedProcedureProvider.GetDataRow("generalLogonFromSessionID", new List<SqlParameter>
{
new SqlParameter("#sessionID", SqlDbType.UniqueIdentifier, oTokenData.TokenId.Length, oTokenData.TokenId),
new SqlParameter("#ipAddress", ipAddress)
});
But if I use a stored procedure that only accepts string parameters, it works fine.
For example:
var dataRow = _storedProcedureProvider.GetDataRow("generalLogon", new List<SqlParameter>
{
new SqlParameter("#loginName", oTokenData.Update.User.EmailAddress),
new SqlParameter("#password", bookingType == BookingType.Commercial ? lastName : "password"),
new SqlParameter("#ipAddress", ipAddress)
});
Does anyone know why?
Current example is using the wrong constructor overload.
public SqlParameter(string parameterName, SqlDbType dbType, int size, string sourceColumn);
Update to use the following
new SqlParameter("#sessionID", SqlDbType.UniqueIdentifier) {
Value = oTokenData.TokenId
};
You supplied the #session parameter, but I don't see you set any value for it..
new SqlParameter("#sessionID", SqlDbType.UniqueIdentifier) { Value = oTokenData.TokenId }
Incidentally, totally appreciate that you're trying to make you life easier by creating a class here that does lots of DB donkey work and means your code becomes simpler.. but it still looks easy to make a mistake (like this). Perhaps take a look at Dapper; it would make the code to exec your proc look more like:
using (var connection = someSqlConnection)
{
var result = connection.Execute("generalLogonFromSessionID",
new {
sessionID = oTokenData.TokenId,
ipAddress = ipAddress
},
commandType: CommandType.StoredProcedure
);
//do something with result
}
No affiliation, just think it's an awesome library that is like what you're trying to achieve, but goes further.. No point reinventing the wheel?
I have stored procedure which takes ID (INT) when I run query using DbContext.Database.SqlQuery I doesn't work. I have another Store Procedure which been script in very similar pattern except it taking all string parameter, perhaps I doing something wrong on this Int passing parameter!!!!
model class
public class DeleteFunctionNavigation_SP_Map
{
public int FunctionID { get; set; }
}
Stored Procedure
ALTER PROCEDURE [dbo].[DeleteFunctionsNavigation]
#FunctionID INT,
#Action_identity INT OUTPUT,
#ActionInFunction_Count INT OUT,
#Controller_identity INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT #Action_identity = Navigation_FunctionInAction.ActionID
FROM Navigation_FunctionInAction
WHERE Navigation_FunctionInAction.Function_ID = #FunctionID
..........
//my other code here!
RETURN
END
C# Class
public void DeleteNavigationFunctionByID(int _FunctionNavigationID)
{
using (var dbContext = new FunctionContext())
{
var Action_identity_out = new SqlParameter("Action_identity", SqlDbType.Int) { Direction = System.Data.ParameterDirection.Output };
var ActionInFunction_Count_out = new SqlParameter("ActionInFunction_Count", SqlDbType.Int) { Direction = System.Data.ParameterDirection.Output };
var Controller_identity_out = new SqlParameter("Controller_identity", SqlDbType.Int) { Direction = System.Data.ParameterDirection.Output };
var _query = dbContext.Database.SqlQuery<DeleteFunctionNavigation_SP_Map>("exec DeleteFunctionsNavigation #FunctionID, #Action_identity out, #ActionInFunction_Count out, Controller_identity out",
new SqlParameter("#FunctionID", SqlDbType.Int).Value = _FunctionNavigationID,
Action_identity_out,
ActionInFunction_Count_out,
Controller_identity_out
);
}
}
Controller Method
[HttpPost]
public ActionResult DeleteFunctionNavigationByID(int _selectedNavigationFunctionID)
{
try
{
_FN_Services_a2.DeleteFunctionNavigationByID(_selectedNavigationFunctionID);
}
catch (Exception ex)
{
ModelState.AddModelError("", "Unable To Delete Requested Record!" + ex);
}
return RedirectToAction("SystemCoreHome");
}
Here's how I did this. I created a function like this:
public int ExecuteNonQueryInt(string commandString, bool isStoredProc = false, params object[] param)
{
int result = 0;
try
{
using (SqlConnection con = new SqlConnection("Your connection string here"))
{
con.Open();
using (SqlCommand cmd = con.CreateCommand())
{
cmd.CommandText = commandString;
cmd.CommandType = isStoredProc ? CommandType.StoredProcedure : CommandType.Text;
foreach (var parm in param)
{
cmd.Parameters.Add(parm);
}
result = cmd.ExecuteNonQuery();
}
con.Close();
}
}
catch (Exception)
{
result = 0;
}
return result;
}
Then I called it like this
SqlParameter[] sqlParameters = new SqlParameter[3]
{
new SqlParameter() { ParameterName = "keywords" , Value = dataTable, SqlDbType = SqlDbType.Structured },
new SqlParameter() { ParameterName = "moduleId" , Value = moduleId, SqlDbType = SqlDbType.UniqueIdentifier },
new SqlParameter() { ParameterName = "createdBy" , Value = createdBy, SqlDbType = SqlDbType.Int }
};
return base.ExecuteNonQueryInt("Your stored procedure", true, sqlParameters) > 0;
I have found the reason why it was not working
1) I use list of against business class
2) I was instantiating SQL parameter wrong or well it did not work for me; working model as following;
public void DeleteNavigationFunctionByID(int _FunctionNavigationID)
{
using (var dbContext = new FunctionContext())
{
List<DeleteFunctionNavigation_SP_Map> _query;
var Action_identity_out = new SqlParameter("Action_identity", SqlDbType.Int) { Direction = System.Data.ParameterDirection.Output };
var ActionInFunction_Count_out = new SqlParameter("ActionInFunction_Count", SqlDbType.Int) { Direction = System.Data.ParameterDirection.Output };
var Controller_identity_out = new SqlParameter("Controller_identity", SqlDbType.Int) { Direction = System.Data.ParameterDirection.Output };
_query = dbContext.Database.SqlQuery<DeleteFunctionNavigation_SP_Map>("exec DeleteFunctionsNavigation #FunctionID, #Action_identity out, #ActionInFunction_Count out, #Controller_identity out",
new SqlParameter("#FunctionID", _FunctionNavigationID),
Action_identity_out,
ActionInFunction_Count_out,
Controller_identity_out
).ToList();
}
}
I want to set value to a literal control using LINQ. I got the result from database in var by the following code:
var result=md.StoredProc_Name(id);
Now I want to assign particular columns value to a literal. As we can do simply in asp.net as bellow with the help of datatable,
dt=obj.Test(id);
ltrlName.Text=dt.Rows[0]["Name"].ToString();
ltrlAddress.Text=dt.Rows[0]["Address"].ToString();
How can we do the same thing in LINQ?
var first = result.FirstOrDefault();
if (first != null)
{
ltrlName.Text = first.Name;
ltrlAddress.Text = first.Address;
}
Addendum - How to do this without linq to objects:
With the code below in a class called DB
var result = DB.SelectIntoItem("StoredProc_Name",
connectionString,
System.Data.CommandType.StoredProcedure,
new { param1 = "val1" });
if (!reader.Empty)
{
ltrlName.Text=result.Name;
ltrlAddress.Text=result.Address;
}
etc.
Code
public static dynamic SelectIntoItem(string SQLselect, string connectionString, CommandType cType = CommandType.Text, object parms = null)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand cmd = conn.CreateCommand())
{
dynamic result = new System.Dynamic.ExpandoObject();
cmd.CommandType = cType;
cmd.CommandText = SQLselect;
if (parms != null)
Addparms(cmd, parms);
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.Read()) // read the first one to get the columns collection
{
var cols = reader.GetSchemaTable()
.Rows
.OfType<DataRow>()
.Select(r => r["ColumnName"]);
foreach (string col in cols)
{
((IDictionary<System.String, System.Object>)result)[col] = reader[col];
}
result.Empty = false;
if (reader.Read())
{
// error, what to do?
result.Error = true;
result.ErrorMessage = "More than one row in result set.";
}
else
{
result.Error = false;
}
}
else
{
result.Empty = true;
result.Error = false;
}
}
conn.Close();
return result;
}
}
}
private static void Addparms(SqlCommand cmd, object parms)
{
// parameter objects take the form new { propname : "value", ... }
foreach (PropertyInfo prop in parms.GetType().GetProperties())
{
cmd.Parameters.AddWithValue("#" + prop.Name, prop.GetValue(parms, null));
}
}
If you are insterested follow my GitHub, I'll be making the rest of it public soon (GitHub)