Many update statements in one Transaction in Entity Framework - asp.net-mvc-3

I need to update more than one update statements, but all should work on automicity i.e update all or none.
on internet and in someother SO Questions i have found how to use Transaction but i didnt' find any of them saying to update mulitple statements in one transaction.
See below three updates statements, currently there not running under transaction
/// this are my update calls.
var report = reportRepository.Update(reportModel);
var book = bookRepository.Update(bookModel);
var mobile = mobileRepository.Update(mobileModel);
// each Update method for all repository will looks like
public returnModel Update(someModel model)
{
// assign values from model to entity
Context.ObjectStateManager.ChangeObjectState(entity,System.Data.EntityState.Modified)
Context.SaveChanges();
}

You could wrap the updates in a TransactionScope:
using (TransactionScope transaction = new TransactionScope())
{
var report = reportRepository.Update(reportModel);
var book = bookRepository.Update(bookModel);
var mobile = mobileRepository.Update(mobileModel);
...
transaction.Complete();
}

As Darin mentioned use a transaction scope or my preferred method is to have your repositories belong to an IUnitOfWork interface. Calling update simply sets the state to modified and the SaveChanges happens OUTSIDE of your repository to save all changes at once.
This should happen automatically inside of one transaction.
So you call all your Updates and then unitOfWork.SaveChanges where your custom unit of work class contains a reference to your context and implements a method defines in IUnitOfWork called Save()

Basically you need to manage it through TransactionScope Class and using this you can set up multiple update to a Model and then use Transaction.Complete to save your stuff in one transaction.
Please check Updating multiple objects in single transaction in entity framework for more details.

Related

Data not updated in oracle-db within the running funtion

From a method callAndUpdateInB(), Suppose I am calling update() method of class B(#Component), in which I am calling an myRepository.save() method to update some data in db, and in same funtion I am performing some other calls ... and then return the response back to class A.
So the problem is data gets updated in db when class B method update() return the response back to class A method callAndUpdateInB().
But it should have updated it when I have called myRepository.save() in update method of class B().
Why so ?
For Reference, just see this dummy example
class A{
#Autowired
B b;
public void callAndUpdateInB(String arg){
String data = b.update(arg);
// check Updates in Db (True)
// Now data is updated in db
}
}
#Component
class B{
#Transactional(
propagation = Propagation.REQUIRED
)
public String update(String arg){
MyRepository myRepository; // This is abstract class having
// imlementation for the following
// data. (MyRepositoryImpl)
String updatedData = myRepository.save(arg);
// check Updates in Db (False)
// Making some other calls, which need that updated data
// But data is not still updated in db.
// Though here the updated data field is showing that the data is updated, but it
// is not actually updated in the db.
return updatedData;
}
}
The transaction will be commited to the database if the method update finishes successfully.
Therefore you can't see the data before the method returns.
Additionally save does not execute the insert/update statement. This will also happen before transaction commit.
If you want to execute the statements before you have to call saveAndFlush(). BUT will also not commit the transaction and from another transaction you will not see this data as well.
This is the usual and expected transactional behavior in a Spring application using transactions.
Propagation REQUIRED
Support a current transaction, create a new one if none exists. Analogous to EJB transaction attribute of the same name.
and keeps the transaction uncommitted and alive at the end of the annotated method.
If you call your update() twice at the very beginning of the request processing, the first starts a transaction and the second reuses it. If you call your update() twice, one successfully, the other unsuccessfully (on unique constraints or something), both of the changes will be rolled back.
Developers usually expect a transaction to start and end like that. But in some cases, a change needs to be committed/rolled back independently from other changes. If it is your case, you can use Propagation.REQUIRES_NEW: See
https://stackoverflow.com/a/24341843/12656244

Asp.Net Boilerplate...How to search in existing tables?

I want to apply queries on Boilerplate default tables in database. But boilerplate uses async methods. How to search in database by Boilerplate framework.
Could you elaborate your question?
I'm not sure what do you want to achieve.
If you uses IRepository you can use both synchronous and asynchronous methods by default.
If you're using asynchronous query and expecting immediate result you can use
If you have to wait for query results you can use Result property of Task. e.g.
var valueImWaitingFor = _repository.GetAllListAsync().Result;
Edit:
Assuming that you want to update user under login you can use provided UserManager class.
var user = loginResult.User; // get your user object
user.Name = "New name"; // edit property
// use one of 3 proposed solutions.
var updatedUser = _userManager.Update(user);
var updatedUser1 = _userManager.UpdateAsync(user).ConfigureAwait(false);
var updatedUser2 = AsyncHelper.RunSync(()=>_userManager.UpdateAsync(user));
Even if you don't use UserManager you can run async call similar way using second and third option.
If you want to use async methods as sync methods then there's a helper class in ABP.
var records = AsyncHelper.RunSync(() => _repository.GetAllListAsync());

javax.persistence.EntityNotFoundException: deleted entity passed to persist

I am using spring + JPA as orm framework. My project layer structure is like web --> Service --> Domain DAO --> genericDAO.
In genericDAO I am injecting EntityManager using #PersistenceContext.
genericDAO.delete(Object o) {
o = entityManager.merge(o);
entityManager.remove(o);
}
genericDAO.saveOrUpdate(Object o) {
entityManager.merge(o);
entityManager.flush();
}
In one method in service layer, I have following operations.
// delete order item if already exists.
Order order = getOrderFromSession();
if (CollectionUtils.isNotEmpty(orderItems)) {
Iterator<OrderItem> iterator = orderItems.iterator();
while (iterator.hasNext()) {
OrderItem orderItem = iterator.next();
iterator.remove();
orderDAO.deleteOrderItem(orderItem); // Which internall calls genericDAO.delete()
}
}
//orderDAO.saveOrder(order) // line Y
//Now create fresh order items submitted by jsp form.
for (ProductVO productVO : productList) {
if (productVO.getQuantity() > 0) {
orderItem = new OrderItem();
Product product = productDAO.getProductByCode(productVO.getCode()); // line X
orderItem.populateOrderItemByProduct(product, productVO.getQuantity(), order);
order.addOrderItem(orderItem);
}
}
Line X retrieve product entity using hql. But when line X is executed, I get below error.
javax.persistence.EntityNotFoundException: deleted entity passed to persist: [core.entity.OrderItem#].
I do not understand if order item is already marked as deleted in entity manager, why it tries to persist.
When I uncomment line Y, which internally flush the entity manager, it works fine. I do not understand why it requires entity manager to be flushed before executing line X
Here is a quote from hibernate documentation
Transactional persistent instances (i.e. objects loaded, saved,
created or queried by the Session) can be manipulated by the
application, and any changes to persistent state will be persisted
when the Session is flushed. There is no need to call a particular method (like update(), which has
a different purpose) to make your modifications persistent. The most
straightforward way to update the state of an object is to load() it
and then manipulate it directly while the Session is open.
Sometimes this programming model is
inefficient, as it requires in the same session both an SQL SELECT to
load an object and an SQL UPDATE to persist its updated state.
Hibernate offers an alternate approach by using detached instances.
But I'll try to explain simplier. Your method getOrderFromSession() is transactional and hibernate objects have session open inside it, but when object order is returned to you, it has been detached from session and hibernate doesn't know what you are doing with it, until you persist him again. So for deleted items hibernate will find out when you save that object, until then object in hibernate have same state as it was in a moment when getOrderFromSession() has return it.
Here you have detailed explanation
UPDATE:
When you delete object in hibernate, object in java becomes transient. It still exist in java and after delete you can use it.
Session.delete() will remove an object's state from the database. Your
application, however, can still hold a reference to a deleted object.
It is best to think of delete() as making a persistent instance,
transient.

MVC 3 and Entity Framework 4.1 data loading issue

Ok!
I have to say both technology are great. Although there seems that something I do not get it.
You have a data in you database (and let say you want to show data from a table that has references to other tables).
I have a model with List or IEnumerable or IQueryable or whatever...
So in my view I want do foreach through the list of object and take advantage of cool feature of references to other tables. No problem in controller while you are in
using (var datatabse = new MyEntity)
{
}
But when you get out of using db has disposed and you get common error The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
So i do not see other options as creating in memory copies of entity objects...but you loose all cool EF4 references and you have to manually load data first in your model and then with foreach show it on the view.
So instead of List<(EF4Type)> or IEnumerable<(EF4Type)> or IQueryable<(EF4Type)>
you have to do List<(MyCustomHelperClass)> where MyCustomHelperClass represents a class with properties similiar to entity objects and probably some additional beacuse you do not have access to properties of referenced tables Then you have to do foreach and Load data into this List and the another #foreach on the view with Razor to show all.
Twice as much work and if project is big...you can see a bigger picture of how manny those helperClasses you need. Was all this cool new technology really meant to be used in that way?....or am I missing something.
You are probably getting that error when you reference a lazy loaded property in your view. You should eager load everything you need in the Controller before passing it to the View.
See Loading Related Objects (Entity Framework).
The following example will cause all courses to be retrieved with the departments in the same query. This is eager loading.
// Load all departments and related courses
var departments1 = context.Departments
.Include(d => d.Courses)
.ToList();
Without the Include() part, courses could be retrieved later (possibly after your context has been disposed in the view). This is called lazy loading.
Along with eager loading as remembered by jrummell, there's also another way of loading related entries, it's explicit loading. Let's suppose you have a User entity, with many Groups entities related to it. You can explicitly load them:
var user = context.Users.Find(id); // Load the user.
context.Entry(user)
.Collection(u => u.Groups)
.Load();
This way you don't have to use the .Include(), and you can even filter the Groups:
context.Entry(user)
.Collection(u => u.Groups)
.Query()
.Where(g => g.SomeProperty.Contains("something"))
.Load();
TheMentor,
Depending on whether you have a repository or a db context, this object should only live for the duration of the controller action (Request), so you should be able to do everything required within the confines of the action.
Maybe i've misunderstood, but based on your question, this is what your issue appears to be. If I have misunderstood, then I'd still suggest that the db repository or db context should be referenced across the controller, rather then invoking it inside the action each time.
so you should see something like this in your controller:
public class TasksController : BaseController
{
private readonly TaskService _serviceTasks;
public TasksController(IRepository repository)
{
_serviceTasks = new TaskService(repository);
}
//
// GET: /Tasks/
public ActionResult Index()
{
var viewModel = _serviceTasks.All<Task>();
return View(viewModel);
}
public ActionResult Details(int id)
{
var domainModel = _serviceTasks.GetById<Task>(id);
var viewModel = PopulateDetailsViewModel(domainModel);
return View(viewModel);
}
//.. rest of actions cut
}

Intercepting context.SaveChanges() in MVC 3 so that I can modify and use a custom sql query instead

I am working on an MVC3 project whose model is designed using Code First approach. I am using EF4 for ORM and have a need where I need two thing -
1. Intercept the context.SaveChages method
2.Do my own custom update query for one specific entity type only.
I got the first part working by overriding the SaveChanges() method like -
public override int SaveChanges()
{
var modifiedItems = this.ChangeTracker.Entries().Where(e => e.State == System.Data.EntityState.Modified && e.Entity is myEntityName);
foreach (var item in modifiedItems)
{
//ToDo: Write UPDATE Sql Query here
}
return base.SaveChanges();
}
How can I write my update query?
Thanks!
This is not possible. You can only map custom stored procedures to be used instead of CUD operations (only with EDMX) generated by EF but still you will have single stored procedure call per each operation and entity instance.

Resources