how to retrieve values from Session object in mvc3? - asp.net-mvc

I have mvc 3 application in which in session object I'm taking all values that is needed to me as parameter to execute stored procedure.
If the userAction is update then execute stored procedure.
public ActionResult Index(string userAction)
{
if(Session["Mappings"] != null)
ViewData["Message"] = "Mapping web grid";
if (Session["PricingSecurities"] == null)
Session["PricingSecurities"] = objRepository.GetPricingSecurityID();
if (Session["Cusips"] == null)
Session["Cusips"] = objRepository.GetCUSIP();
SecurityMappingModel objModel = null;
mappings = (List<SecurityMappingModel>)Session["Mappings"];
objModel = new SecurityMappingModel();
if (userAction == "Update" )
{
//please tell me how can i take values from Session[Mappings] and pass it to stored procedure?
//i'm trying this code
//foreach (var item in Session)
//{objModel.Cusips = (List<SelectListItem>)Session["Mappings"];
//I did function import here (import my sp in model)using EF name
//ExecuteMappingsp.
//dbContext.ExecuteMappingsp(need to pass parameter);
//} //i know wrong code but how to fix this??
// PLEASE HELP ME TO RETRIEVE SESSION VALUES
return RedirectToAction("Index");
}
objModel.PricingSecirities = (List<SelectListItem>)Session["PricingSecurities"];
objModel.Cusips = (List<SelectListItem>)Session["Cusips"];
ViewBag.Mappings = mappings;
return View(objModel);
}
How can I take values from Session[Mappings] and pass it to stored procedure?

Description
Entity Framework Code First does not support stored procedure calls at the moment. The only way to do this, at the moment, is to use the SqlCommand. (System.Data.SqlClient namespace)
Sample
// ....
if (userAction == "Update")
{
// Create SqlCommand with your stored procedure name and sql connectionstring
SqlCommand cmd = new SqlCommand("dbo.StoredProcedureName", new SqlConnection("ConnectionString"));
// set the command type to StoredProcedure
cmd.CommandType = System.Data.CommandType.StoredProcedure;
// Add Parameters
cmd.Parameters.Add("#ParameterName", Session[Mappings]);
// execute the stored procedure
cmd.ExecuteNonQuery();
return RedirectToAction("Index");
}
More Information
MSDN - Using Stored Procedures with a Command
Update
I can't know your Model and if it is code first, database first or shema first because you don't provide that information. But maybe this helps
foreach (var item in (List<SelectListItem>)Session["Mappings"])
{
dbContext.ExecuteMappingsp(PassInTheParametersYouNeedFromYourItem)
}

Related

Generic procedure execution method for DAL incl. parameters

I am trying to create a "generic" method in a data access layer that executes a passed stored procedure in Sql Server and also takes a list / array / collection of SqlParameters, to make the usage of a stored procedure call within other parts of the code easier (without requirement to care for connection, command objects etc).
The goal is sth. like this:
int iAffectedRows = dal.RunProcedure("dbo.mySP", parameters);
The parameters should of course be defined previously but without the types. I want them to be created using the AddwithValue() method of SqlParameterCollection class.
It looks like it's impossible because the SqlParameterCollection class can't be instanciated. Look at this discussion.
Anyone knows how to create this?
It's not a good idea to send in a DbParameterCollection (SqlParameterCollection), since it's tightly coupled (which you have discovered) with the ADO.NET infrastructure that you're trying to abstract away. It's better to map your own parameter representation to the collection inside your method.
You can solve it using something like this:
public class DataAccess
{
private ConnectionStringSettings _settings;
public DataAccess(ConnectionStringSettings settings)
{
_settings = settings;
}
public int RunProcedure(string name, dynamic parameters)
{
using (var conn = CreateConnection())
using (var command = CreateCommand(conn, name, parameters))
{
return command.ExecuteNonQuery();
}
}
private DbConnection CreateConnection()
{
var factory = DbProviderFactories.GetFactory(_settings.ProviderName);
var connection = factory.CreateConnection();
connection.ConnectionString = _settings.ConnectionString;
connection.Open();
return connection;
}
private DbCommand CreateCommand(DbConnection conn, string commandText,
object parameters)
{
var cmd = conn.CreateCommand();
cmd.CommandText = commandText;
cmd.CommandType = CommandType.StoredProcedure;
foreach(PropertyInfo parameter in parameters.GetType().GetProperties())
{
var commandParameter = cmd.CreateParameter();
commandParameter.ParameterName = "#" + parameter.Name;
commandParameter.Value = parameter.GetValue(parameters);
cmd.Parameters.Add(commandParameter);
}
return cmd;
}
}
Callable with a syntax like this:
dal.RunProcedure("dbo.mySP", new {
Parameter1 = value1,
Parameter2 = value2
});
You can greatly simplify the code if you only want to support SqlClient.
But instead of rolling this on your own, use a ready made stable library, such as Dapper.
I ended up with the following solution:
SqlParameter[] parameters = {
new SqlParameter("#p1", SqlDbType.Int) { Value = 999},
new SqlParameter("#p2", SqlDbType.Char, 30, "source") { Value = "test"}
};
da.RunProcedure("[dbo].[SP1]", parameters, out rowsAffected);
The RunProcedure accepts IDataParameter[] parameters and forwards this to an command builder method that adds each single of them into the SqlParameters Property of my SqlCommand object:
private static SqlCommand BuildQueryCommand(string storedProcName, IDataParameter[] parameters)
{
SqlCommand command = new SqlCommand( storedProcName, GetDBConnection() );
command.CommandType = CommandType.StoredProcedure;
if (parameters != null)
{
foreach (SqlParameter parameter in parameters)
{
command.Parameters.Add( parameter );
}
}
return command;
}
This works fine and this way I can add each Param with 1 single line of code (that was my destination #1) incl. all Properties of SqlParameter available (use SqlDBType if required, this is up to the user).

Best Way to Update only modified fields with Entity Framework

Currently I am doing like this:
For Example:
public update(Person model)
{
// Here model is model return from form on post
var oldobj = db.Person.where(x=>x.ID = model.ID).SingleOrDefault();
db.Entry(oldobj).CurrentValues.SetValues(model);
}
It works, but for example,
I have 50 columns in my table but I displayed only 25 fields in my form (I need to partially update my table, with remaining 25 column retain same old value)
I know it can be achieve by "mapping columns one by one" or by creating "hidden fields for those remaining 25 columns".
Just wondering is there any elegant way to do this with less effort and optimal performance?
This is a very good question. By default I have found that as long as change tracking is enabled (it is by default unless you turn it off), Entity Framework will do a good job of applying to the database only what you ask it to change.
So if you only change 1 field against the object and then call SaveChanges(), EF will only update that 1 field when you call SaveChanges().
The problem here is that when you map a view model into an entity object, all of the values get overwritten. Here is my way of handling this:
In this example, you have a single entity called Person:
Person
======
Id - int
FirstName - varchar
Surname - varchar
Dob - smalldatetime
Now let's say we want to create a view model which will only update Dob, and leave all other fields exactly how they are, here is how I do that.
First, create a view model:
public class PersonDobVm
{
public int Id { get; set; }
public DateTime Dob { get; set; }
public void MapToModel(Person p)
{
p.Dob = Dob;
}
}
Now write the code roughly as follows (you'll have to alter it to match your context name etc):
DataContext db = new DataContext();
Person p = db.People.FirstOrDefault();
// you would have this posted in, but we are creating it here just for illustration
var vm = new PersonDobVm
{
Id = p.Id, // the Id you want to update
Dob = new DateTime(2015, 1, 1) // the new DOB for that row
};
vm.MapToModel(p);
db.SaveChanges();
The MapToModel method could be even more complicated and do all kinds of additional checks before assigning the view model fields to the entity object.
Anyway, the result when SaveChanges is called is the following SQL:
exec sp_executesql N'UPDATE [dbo].[Person]
SET [Dob] = #0
WHERE ([Id] = #1)
',N'#0 datetime2(7),#1 int',#0='2015-01-01 00:00:00',#1=1
So you can clearly see, Entity Framework has not attempted to update any other fields - just the Dob field.
I know in your example you want to avoid coding each assignment by hand, but I think this is the best way. You tuck it all away in your VM so it does not litter your main code, and this way you can cater for specific needs (i.e. composite types in there, data validation, etc). The other option is to use an AutoMapper, but I do not think they are safe. If you use an AutoMapper and spelt "Dob" as "Doob" in your VM, it would not map "Doob" to "Dob", nor would it tell you about it! It would fail silently, the user would think everything was ok, but the change would not be saved.
Whereas if you spelt "Dob" as "Doob" in your VM, the compiler will alert you that the MapToModel() is referencing "Dob" but you only have a property in your VM called "Doob".
I hope this helps you.
I swear by EntityFramework.Extended. Nuget Link
It lets you write:
db.Person
.Where(x => x.ID == model.ID)
.Update(p => new Person()
{
Name = newName,
EditCount = p.EditCount+1
});
Which is very clearly translated into SQL.
Please try this way
public update(Person model)
{
// Here model is model return from form on post
var oldobj = db.Person.where(x=>x.ID = model.ID).SingleOrDefault();
// Newly Inserted Code
var UpdatedObj = (Person) Entity.CheckUpdateObject(oldobj, model);
db.Entry(oldobj).CurrentValues.SetValues(UpdatedObj);
}
public static object CheckUpdateObject(object originalObj, object updateObj)
{
foreach (var property in updateObj.GetType().GetProperties())
{
if (property.GetValue(updateObj, null) == null)
{
property.SetValue(updateObj,originalObj.GetType().GetProperty(property.Name)
.GetValue(originalObj, null));
}
}
return updateObj;
}
I have solved my Issue by using FormCollection to list out used element in form, and only change those columns in database.
I have provided my code sample below; Great if it can help someone else
// Here
// collection = FormCollection from Post
// model = View Model for Person
var result = db.Person.Where(x => x.ID == model.ID).SingleOrDefault();
if (result != null)
{
List<string> formcollist = new List<string>();
foreach (var key in collection.ToArray<string>())
{
// Here apply your filter code to remove system properties if any
formcollist.Add(key);
}
foreach (var prop in result.GetType().GetProperties())
{
if( formcollist.Contains(prop.Name))
{
prop.SetValue(result, model.GetType().GetProperty(prop.Name).GetValue(model, null));
}
}
db.SaveChanges();
}
I still didn't find a nice solution for my problem, so I created a work around. When loading the Entity, I directly make a copy of it and name it entityInit. When saving the Entity, I compare the both to see, what really was changed. All the unchanged Properties, I set to unchanged and fill them with the Database-Values. This was necessary for my Entities without Tracking:
// load entity without tracking
var entityWithoutTracking = Context.Person.AsNoTracking().FirstOrDefault(x => x.ID == _entity.ID);
var entityInit = CopyEntity(entityWithoutTracking);
// do business logic and change entity
entityWithoutTracking.surname = newValue;
// for saving, find entity in context
var entity = Context.Person.FirstOrDefault(x => x.ID == _entity.ID);
var entry = Context.Entry(entity);
entry.CurrentValues.SetValues(entityWithoutTracking);
entry.State = EntityState.Modified;
// get List of all changed properties (in my case these are all existing properties, including those which shouldn't have changed)
var changedPropertiesList = entry.CurrentValues.PropertyNames.Where(x => entry.Property(x).IsModified).ToList();
foreach (var checkProperty in changedPropertiesList)
{
try
{
var p1 = entityWithoutTracking.GetType().GetProperty(checkProperty).GetValue(entityWithoutTracking);
var p2 = entityInit.GetType().GetProperty(checkProperty).GetValue(entityInit);
if ((p1 == null && p2 == null) || p1.Equals(p2))
{
entry.Property(checkProperty).CurrentValue = entry.Property(checkProperty).OriginalValue; // restore DB-Value
entry.Property(checkProperty).IsModified = false; // throws Exception for Primary Keys
}
} catch(Exception) { }
}
Context.SaveChanges(); // only surname will be updated
This is way I did it, assuming the new object has more columns to update that the one we want to keep.
if (theClass.ClassId == 0)
{
theClass.CreatedOn = DateTime.Now;
context.theClasses.Add(theClass);
}
else {
var currentClass = context.theClasses.Where(c => c.ClassId == theClass.ClassId)
.Select(c => new TheClasses {
CreatedOn = c.CreatedOn
// Add here others fields you want to keep as the original record
}).FirstOrDefault();
theClass.CreatedOn = currentClass.CreatedOn;
// The new class will replace the current, all fields
context.theClasses.Add(theClass);
context.Entry(theClass).State = EntityState.Modified;
}
context.SaveChanges();
In EF you can do like this
var result = db.Person.Where(x => x.ID == model.ID).FirstOrDefault();
if(result != null){
result.Name = newName;
result.DOB = newDOB;
db.Person.Update(result);
}
Or you can use
using (var db= new MyDbContext())
{
var result= db.Person.Where(x => x.ID == model.ID).FirstOrDefault();
result.Name= newName;
result.DOB = newDOB;
db.Update(result);
db.SaveChanges();
}
For more detail please EntityFramework Core - Update Only One Field
No Worry guys
Just write raw sql query
db.Database.ExecuteSqlCommand("Update Person set Name='"+_entity.Name+"' where Id = " + _entity.ID + "");

how to pass parameters to stored procedure in mvc 3 using EF?

I have mvc 3 application in which in session object i'm taking all values that is needed
to me as parameter to execute stored procedure.
If the userAction is update then execute stored procedure.
public ActionResult Index(string userAction)
{
if(Session["Mappings"] != null)
ViewData["Message"] = "Mapping web grid";
if (Session["PricingSecurities"] == null)
Session["PricingSecurities"] = objRepository.GetPricingSecurityID();
if (Session["Cusips"] == null)
Session["Cusips"] = objRepository.GetCUSIP();
SecurityMappingModel objModel = null;
mappings = (List<SecurityMappingModel>)Session["Mappings"];
objModel = new SecurityMappingModel();
if (userAction == "Update" )
{
//please tell me how can i take values from Session[Mappings] and pass it to stored procedure?
return RedirectToAction("Index");
}
objModel.PricingSecirities = (List<SelectListItem>)Session["PricingSecurities"];
objModel.Cusips = (List<SelectListItem>)Session["Cusips"];
ViewBag.Mappings = mappings;
return View(objModel);
}
How can i take values from Session[Mappings] and pass it to stored procedure?
You would need to do something like this:
using (MyEntitiesDataModel context = new MyEntitiesDataModel())
{
context.ExecuteStoreCommand(
"exec MyStoredProc #param1={0}, #param2={1}",
Session["foo"], Session["bar"]);
}
...where MyEntitiesDataModel is your EF data model and MyStoredProc is the name of your stored proc.

Asp.Net MVC 3 - Linq To Entities - PK with Null doesn't get inserted into the db (don't want null :))

I'm using the latest Asp.Net MVC version.
For some reason, when my POST (Action Create) in my controller gets hit.
I can't seem to be able to add it to the entityset.
What i have is,
1) My EntityModel (*.edmx file)
2) Controller which references the entity:
private db.DataContainer _db = new db.DataContainer();
3) My method (i'm using Guid as pk):
[HttpPost]
public ActionResult Create(Client client)
{
try
{
client.Id = Guid.NewGuid();
/* method 2
Client cl = new Client();
cl.Id = Guid.NewGuid();
cl.email = client.email;
cl.Adres = client.Adres;
cl.companyName = client.companyName;
cl.fax = client.fax;
cl.phone = client.phone;
*/
// client.Id = Guid.NewGuid();
_db.ClientSet.AddObject(client);
_db.SaveChanges();
return RedirectToAction("Index");
}
catch (Exception ex)
{
var ex_message = ex.Message;
var ex_data = ex.Data;
var ex_ix = ex.InnerException;
return View();
}
}
4) Following is my InnerException:
[System.Data.SqlClient.SqlException] = {"Cannot insert the value NULL into column 'Id', table 'lst.dbo.ClientSet'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated."}
Both doesn't seem to work :(
GUIDs are not supported as primary keys in the Entity Framework. You will need to modify your save method to generate a new GUID for your added objects http://msdn.microsoft.com/en-us/library/dd283139.aspx
It seems that changing my "saveCommand" has given my a temporarily solution:
I chaned:
_db.SaveChanges()
To
_db.SaveChanges(System.Data.Objects.SaveOptions.None);

SubSonic Return ExecuteSingle for Stored Procedure

I wish to return a single ScPollOption item using a Stored Procedure via the code below:
public ScPollOption FetchPollOptionByID(int optionID)
{
StoredProcedure sp = SPs.ScPollOptionGetOptionByID(optionID);
return sp;
}
When working with a query I would use:
ExecuteSingle<ScPollOption>()
but SubSonic only allows for sp.ExecuteTypedList<> and sp.ExecuteScalar<>.
How can I return a single ScPollOption item?
Thanks
Dan
I know it's not terribly attractive, but this would work if you're able to use the LINQ extensions:
sp.ExecuteTypedList<ScPollOption>().FirstOrDefault();
You could also execute an IDataReader and inflate the ScPollOption object manually:
ScPollOption item;
using (IDataReader reader = sp.ExecuteReader())
{
if (reader.Read())
{
item = new ScPollOption();
item.SomeProperty = reader.GetValue(0);
// Set additional properties
}
}
return item;

Resources