I read that the new Entity Framework will include a method to delete multiple items (Linq to SQL has DeleteAllOnSubmit()) but I can't find the function/method to do that.
Is this in Beta 2 or do I have to make my own?
UPDATE:
This is what I'm using now:
public void DeleteObjects(IEnumerable<object> objects)
{
foreach (object o in objects)
{
DeleteObject(o);
}
SaveChanges();
}
EF 4 allows you to execute TSQL statements against an object context:
using (var context = new EntityFrameworkExampleEntities())
{
var count =
context.ExecuteStoreCommand(#"DELETE FROM Companies WHERE [CompanyID]=4");
}
See the following blog for details.
http://blogs.microsoft.co.il/blogs/gilf/archive/2009/11/25/execute-t-sql-statements-in-entity-framework-4.aspx
I know this is late, but I found this post and found a simpler solution, that wasn't posted.
You can set OnDelete to Cascade in the Association properties. In VS2012 open the edmx file. Click on the association and you'll find the OnDelete in the Properties tab. Then you can use the Remove() method with no triggers or any other special handling.
Related
I am trying to update an object after retrieving it from a database.
This fires 2 queries , one for the select and the other for the update, is there any way of update an object using Fluent NHiberNate firing only one query ?
My code is as below:
var userProfile = userProfileRepository
.Find(x => x.ClientId == clientId)
.FirstOrDefault();
/* update UserProfile object here */
userProfileRepository.SaveOrUpdate(userProfile);
the SaveOrUpdate Method looks as such :
public bool SaveOrUpdate(T instance)
{
using (var session = SessionManager.OpenSession())
{
using (var transaction = session.BeginTransaction())
{
session.SaveOrUpdate(instance);
transaction.Commit();
}
return true;
}
}
In case that your issue is:
regardless of what I do, SaveOrUpdate() always sends SELECT then UPDATE
You should check the doc:
5.1.4.7. Assigned Identifiers
If you want the application to assign identifiers (as opposed to having NHibernate generate them), you may use the assigned generator. This special generator will use the identifier value already assigned to the object's identifier property. Be very careful when using this feature to assign keys with business meaning (almost always a terrible design decision).
Due to its inherent nature, entities that use this generator cannot be saved via the ISession's SaveOrUpdate() method. Instead you have to explicitly specify to NHibernate if the object should be saved or updated by calling either the Save() or Update() method of the ISession.
So, if your Fluent configuration sets the ID to be assigned - NHibernate has no other way then check if it
exists
or is new
because used method was SaveOrUpdate()
Solution(s)
1) Change the ID to be generated by DB or NHiberante 2) use explicit Update()
Are you trying to create an
UPDATE ... WHERE ...
statement?
AFAIK the NHibernate way to do this, is to select the appropriate objects (using the WHERE clause), update the fields, and persist them again.
var tempObjects = _session.Query<myObject>.Where(o => o.Id > 500);
// update proxy objects
foreach (var o in tempObjects)
{
o.MyValue = updatedValue;
}
// commit updated objects
_session.Update(tempObjects);
To be honest, we've used ISession.CreateSQLQuery ourselves. I hate using SQL in code because it breaks in refactoring, but if you must - here's how:
_session.CreateSQLQuery(
#"UPDATE [MyTable] SET [MyValue]=:updatedvalue WHERE Id > 500")
.SetParameter("updatedvalue", updatedValue)
.ExecuteUpdate();
I used Entity Framework to create a prototype for a project and now that it's working I want to make the program ready for production.
I face many challenges with EF, the biggest one being the concurrency management (it's a financial software).
Given that it seems to have no way to handle pessimistic concurrency with EF, I have to switch to stored procs in SQL.
To be honest I'm a bit afraid of the workload that may represent.
I would like to know if anybody have been in the same situation before and what is the best strategy to convert a .net code using EF to raw SQL.
Edit:
I'm investigating CLR but it's not clear if pessimistic concurency can be manage with it. is it an option more interesting than TSQl in this case ? It would allow me to reuse part of my C# code and structure of function calling another functions, if I understand well.
I was there and the good news is you don't have to give up Entity Framework if you don't want to. The bad news is you have to update the database yourself. Which isn't as hard as it seems. I'm currently using EF 5 but plan to go to EF 6. I don't see why this still wouldn't work for EF 6.
First thing is in the constructor of the DbContext cast it to IObjectContextAdapter and get access to the ObjectContext. I make a property for this
public virtual ObjectContext ObjContext
{
get
{
return ((IObjectContextAdapter)this).ObjectContext;
}
}
Once you have that subscribe to the SavingChanges event - this isn't our exact code some things are copied out of other methods and redone. This just gives you an idea of what you need to do.
ObjContext.SavingChanges += SaveData;
private void SaveData(object sender, EventArgs e)
{
var context = sender as ObjectContext;
if (context != null)
{
context.DetectChanges();
var tsql = new StringBuilder();
var dbParams = new List<KeyValuePair<string, object>>();
var deletedEntites = context.ObjectStateManager.GetObjectStateEntries(EntityState.Deleted);
foreach (var delete in deletedEntites)
{
// Set state to unchanged - so entity framework will ignore
delete.ChangeState(EntityState.Unchanged);
// Method to generate tsql for deleting entities
DeleteData(delete, tsql, dbParams);
}
var addedEntites = context.ObjectStateManager.GetObjectStateEntries(EntityState.Added);
foreach (var add in addedEntites)
{
// Set state to unchanged - so entity framework will ignore
add.ChangeState(EntityState.Unchanged);
// Method to generate tsql for added entities
AddData(add, tsql, dbParams);
}
var editedEntites = context.ObjectStateManager.GetObjectStateEntries(EntityState.Modified);
foreach (var edit in editedEntites)
{
// Method to generate tsql for updating entities
UpdateEditData(edit, tsql, dbParams);
// Set state to unchanged - so entity framework will ignore
edit.ChangeState(EntityState.Unchanged);
}
if (!tsql.ToString().IsEmpty())
{
var dbcommand = Database.Connection.CreateCommand();
dbcommand.CommandText = tsql.ToString();
foreach (var dbParameter in dbParams)
{
var dbparam = dbcommand.CreateParameter();
dbparam.ParameterName = dbParameter.Key;
dbparam.Value = dbParameter.Value;
dbcommand.Parameters.Add(dbparam);
}
var results = dbcommand.ExecuteNonQuery();
}
}
}
Why we set the entity to unmodified after the update because you can do
var changed properties = edit.GetModifiedProperties();
to get a list of all the changed properties. Since all the entities are now marked as unchanged EF will not send any updates to SQL.
You will also need to mess with the metadata to go from entity to table and property to fields. This isn't that hard to do but messing the metadata does take some time to learn. Something I still struggle with sometimes. I refactored all that out into an IMetaDataHelper interface where I pass it in the entity type and property name to get the table and field back - along with caching the result so I don't have to query metadata all the time.
At the end the tsql is a batch that has all the T-SQL how we want it with the locking hints and containing the transaction level. We also change numeric fields from just being set to nfield = 10 but to be nfield = nfield + 2 in the TSQL if the user updated them by 2 to avoid the concurrency issue as well.
What you wont get to is having SQL locked once someone starts to edit your entity but I don't see how you would get that with stored procedures as well.
All in all it took me about 2 solid days to get this all up and running for us.
I've been banging my head off what should be a simple issue. I'm trying to do the following basic operation
1) Check if entity exists by a field other than ID
2) If not, create entity
Problem is this is in a console app that is multi-threaded, so I need to somehow get an entity by a field other than the ID and set the LockMode to Upgrade (or at least I think thats what needs to be done). From what I see there is no way to do that with ISession.
Any ideas?
in a single process use a global lockobject
lock(existsLocker)
{
var entity = session.Query<Entity>().Where(...).FirstOrDefault();
if (entity == null)
{
entity = new Entity();
session.Save(entity);
session.Flush();
}
}
I have a really weird scenario where I try to store domain events (I'm trying to learn CQRS and RavenDB at the same time). The basic structure of the documents I try to store are:
public interface IDomainEvent { ... }
public abstract class BaseDomainEvent : IDomainEvent { ... }
public class DomainEventA : BaseDomainEvent { ... }
public class DomainEventB : BaseDomainEvent { ... }
Given that I want to store DomainEventA and DomainEventB in the same collection in RavenDB and I have managed to do so. But the problem is that in the collection I am missing the properties of DomainEventB, and not all properties are set even though I have checked that the properties are set before I commit the transaction where I store the objects. The following gist shows a working example of what I want to do: https://gist.github.com/2830093, and the test code that fails me is found in this test: https://github.com/mastoj/TJ.CQRS/blob/ravenfail/TJ.CQRS.RavenEvent.Tests/RavenEventStoreTests.cs that is using this RavenDB code: https://github.com/mastoj/TJ.CQRS/blob/ravenfail/TJ.CQRS.RavenEvent/RavenEventStore.cs.
I really can't get my head around this one.
EDIT 1: I can add that in the failing scenario the metadata of the stored object says it is one type but the properties for that type is not stored.
I planned to delete or vote for close but I think more than me might experience this problem at some point. I found the solution in my case and it was that the objects I added to RavenDB had a faulty equals method so RavenDB thought that all my objects were the same one. When I added one more property to check in the equals method everything start working as expected.
I am attempting to create an abstracted getId method on my base Entity class in Symfony2 using Doctrine2 for a database where primary keys are named inconsistently across tables.
When inspecting entity objects I see there is a private '_identifier' property that contains the information I am trying to retrieve but I am not sure how to properly access it.
I'm assuming there is some simple Doctrine magic similar to:
public function getId()
{
return $this->getIdentifier();
}
But I haven't managed to find it on the intertubes anywhere.
You can access this information via EntityManager#getClassMetadata(). An example would look like this:
// $em instanceof EntityManager
$meta = $em->getClassMetadata(get_class($entity));
$identifier = $meta->getSingleIdentifierFieldName();
If your entity has a composite primary key, you'll need to use $meta->getIdentifierFieldNames() instead. Of course, using this method, you'll need access to an instance of EntityManager, so this code is usually placed in a custom repository rather than in the entity itself.
Hope that helps.