Stub Update an Entity in Entity Framework - asp.net-mvc

I want update an entity property(Count) in Entity Framework 6 with stub update manner, indeed i want plus one Count property value Without query database. How i can do this?
//...
var stub = new entity {Id = id};
_articles.Attach(stub);
stub.Count++; // Count always is 1! How i can do this without fetch/query database?
context.SaveChanges();
//...

The only way I'm aware of is to use a stored procedure.
create proc sp_UpdateCount #Id int
as
update [dbo].[EntityTable] set [Count] = [Count] + 1
where [Id] = #Id
and then run it in the code
SqlParameter paramId = new SqlParameter("#Id", id);
context.Database.ExecuteSqlCommand("sp_UpdateCount #Id", paramId);
Please note this will run the procedure immediately and you don't have to call SaveChanges for it. If you want to execute the procedure in a transaction with other changes make sure you create one explicitly with TransactionScope.
Hope it helps!

Related

Stored procedure returning dynamic columns in Entity Framework

I have a function calling a SQL Server stored procedure using Entity Framework 6.2.
The stored procedure returns a result set which has different number of columns on each call, and column names may vary on each call.
Function getListOfDocs() As JsonResult
Try
Using entities As PromatEntities = New PromatEntities()
Dim param(1) As SqlParameter
param(0) = New SqlParameter("#ProjID", SqlDbType.Int)
param(0).Value = vProjectId
Dim query = entities.Database.SqlQuery(Of "help required here")("sp_EIP_IPSSDocMaster_Get", param) // cannot handle this case as entity framework needs type
Dim lstDocs = query.ToList
End Using
Return Json(New With {lstDocs}, JsonRequestBehavior.AllowGet)
Catch ex As Exception
ClsCommon.ExceptionManager(ex)
Return Nothing
End Try
End Function
But Entity Framework doesn't allow anonymous types in database.SqlQuery. Can anyone suggest a way to solve the issue and get the anonymous type data to view?

Will SaveChanges inside Entity Framework wraps all changes in a database transaction

I have the following method inside my asp.net mvc web application, and i am using Ado.net entity framework to map my current database tables:-
public void changeDeviceSwitch(int fromID , int toID)
{
var currentdevices = tms.TMSSwitchPorts.Where(a => a.SwitchID == fromID);
foreach (var d in currentdevices)
{
tms.TMSSwitchPorts.Remove(d);
}
foreach (var d in currentdevices)
{
TMSSwitchPort tsp = new TMSSwitchPort()
{ SwitchID = toID,
TechnologyID = d.TechnologyID,
PortNumber = d.PortNumber };
tms.TMSSwitchPorts.Add(d);
}
tms.SaveChanges();
}
My above method will generate multiple delete and add operations inside the database. so let say it will result in 5 delete operations and 5 insert operations, in this case will calling the SaveChangies() in my case, wraps the 10 operations in one database transaction ?, so either all changes happen or none of them ?
Thanks
That is correct, SaveChanges acts like transaction meaning nothing is happening until you call it explicitly (nothing is sent to DB), and once you call it, everything is sent at once, and if one query/command fails, no changes will be persisted.
If you however want to send queries to SQL in batches, but still treat them as single transaction, you might look into what Entity Framework 6 has to offer (MSDN Article). Basically, you can wrap several SaveChanges in one big transaction, and if any of the queries/commands sent to SQL fails, in any of the batches, it will allow you to do a rollback of everything.

Getting only what is needed with Entity Framework

With a plain connection to SQL Server, you can specify what columns to return in a simple SELECT statement.
With EF:
Dim who = context.Doctors.Find(3) ' Primary key is an integer
The above returns all data that entity has... BUT... I would only like to do what you can with SQL and get only what I need.
Doing this:
Dim who= (From d In contect.Doctors
Where d.Regeneration = 3
Select New Doctor With {.Actor = d.Actor}).Single
Gives me this error:
The entity or complex type XXXXX cannot be constructed in a LINQ to Entities query.
So... How do I return only selected data from only one entity?
Basically, I'm not sure why, but Linq can't create the complex type. It would work if you were creating a anonymous type like (sorry c# code)
var who = (from x in contect.Doctors
where x.Regeneration == 3
select new { Actor = x.Actor }).Single();
you can then go
var doctor = new Doctor() {
Actor = who.Actor
};
but it can't build it as a strongly typed or complex type like you're trying to do with
var who = (from x in contect.Doctors
where x.Regeneration == 3
select new Doctor { Actor = x.Actor }).Single();
also you may want to be careful with the use of single, if there is no doctor with the regeneration number or there are more than one it will throw a exception, singleordefault is safer but it will throw a exception if there is more than one match. First or Firstordefault are much better options First will throw a exception only if none exist and Firstordefault can handle pretty much anything
The best way to do this is by setting the wanted properties in ViewModel "or DTO if you're dealing with upper levels"
Then as your example the ViewModel will be:
public class DoctorViewModel{
public string Actor {get;set;}
// You can add as many properties as you want
}
then the query will be:
var who = (From d In contect.Doctors
Where d.Regeneration = 3
Select New DoctorViewModel {Actor = d.Actor}).Single();
Sorry i wrote the code with C# but i think the idea is clear :)
You can just simply do this:
Dim who= (From d In contect.Doctors
Where d.Regeneration = 3
Select d.Actor).Single
Try this
Dim who = contect.Doctors.SingleOrDefault(Function(d) d.Regeneration = 3).Actor

CLR Stored Procedure

I wish to use the Cryptography API in CLR stored procedure.
I have created a CLR stored procedure and written a select statement
SqlConnection conn = new SqlConnection();
conn.ConnectionString = "Context Connection=true";
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = #"select * from Employee";
SqlDataReader rdr = cmd.ExecuteReader();
Now I wish to filter the results using the employee Number which is stored in encrypted form in database for which I am going to use the Cryptography methods.
Now I am stuck with how to go about filtering the records from the SqlDataReader.
I want the return format as SqlDataReader, as to return multiple records from CLR stored procedure there is one method SqlContext.Pipe.Send() and this method accepts only SqlDataReader objects.
Please guide me.
I'm looking at a similar problem where I want to do some manipulation before returning the results.
The only way I can see at the moment is to use:
// Note you need to pass an array of SqlMetaData objects to represent your columns
// to the constructor of SqlDataRecord
SqlDataRecord record = new SqlDataRecord();
// Use the Set methods on record to supply the values for the first row of data
SqlContext.Pipe.SendResultsStart(record);
// for each record you want to return
// use set methods on record to populate this row of data
SqlContext.Pipe.SendResultsRow(record);
Then call SqlContext.Pipe.SendResultsEnd when you're done.
If theres a better way I'd like to know too!

Entity Framework CTP5 - Reading Multiple Record Sets From a Stored Procedure

In EF4, this was not easily possible. You either had to degrade to classic ADO.NET (DataReader), use ObjectContext.Translate or use the EFExtensions project.
Has this been implemented off the shelf in EF CTP5?
If not, what is the recommended way of doing this?
Do we have to cast the DbContext<T> as an IObjectContextAdapter and access the underlying ObjectContext in order to get to this method?
Can someone point me to a good article on doing this with EF CTP5?
So i got this working, here's what i have:
internal SomeInternalPOCOWrapper FindXXX(string xxx)
{
Condition.Requires(xxx).IsNotNullOrEmpty();
var someInternalPokey = new SomeInternalPOCOWrapper();
var ctx = (this as IObjectContextAdapter).ObjectContext;
var con = new SqlConnection("xxxxx");
{
con.Open();
DbCommand cmd = con.CreateCommand();
cmd.CommandText = "exec dbo.usp_XXX #xxxx";
cmd.Parameters.Add(new SqlParameter("xxxx", xxx));
using (var rdr = cmd.ExecuteReader())
{
// -- RESULT SET #1
someInternalPokey.Prop1 = ctx.Translate<InternalPoco1>(rdr);
// -- RESULT SET #2
rdr.NextResult();
someInternalPokey.Prop2 = ctx.Translate<InternalPoco2>(rdr);
// -- RESULT SET #3
rdr.NextResult();
someInternalPokey.Prop3 = ctx.Translate<InternalPoco3>(rdr);
// RESULT SET #4
rdr.NextResult();
someInternalPokey.Prop4 = ctx.Translate<InternalPoco4>(rdr);
}
con.Close();
}
return someInternalPokey;
}
Essentially, it's basically like classic ADO.NET. You read the DbReader, advance to the next result set, etc.
But at least we have the Translate method which seemingly does a left-to-right between the result set fields and the supplied entity.
Note the method is internal.
My Repository calls this method, then hydrates the DTO into my domain objects.
I'm not 100% happy with it for 3 reasons:
We have to cast the DbContext as IObjectContextAdapter. The method Translate should be on DbContext<T> class IMO.
We have to use classic ADO.NET Objects. Why? Stored Procedures are a must have for any ORM. My main gripe with EF is the lack of the stored procedure support and this seems to not have been rectified with EF CTP5.
You have to open a new SqlConnection. Why can't it use the same connection as the one opened by the EF Context?
Hope this both helps someone and sends out a message to the EF team. We need multiple result support for SPROCS off the shelf. You can map a stored proc to a complex type, so why can't we map a stored proc to multiple complex types?

Resources