How do I update a Manage Realm object?
If I run this twice it fails, saying the object is already managed. I understand the Exception, but how do I update/delete the object after it is managed?
using (var instance2 = Realm.GetInstance())
{
using (var transaction = instance2.BeginWrite())
{
foreach (var item in items)
{
instance2.Manage(item);
}
transaction.Commit();
}
}
There is no need to Manage an object a second time. Once it's been added to the Realm by calling Manage, it becomes a "live" object - every change you make will be persisted. So if you have a list of employees:
var instance = Realm.GetInstance();
using (var transaction = instance.BeginTransaction())
{
foreach (var e in employees)
{
instance.Manage(e);
}
transaction.Commit();
}
And then you want to, say, calculate their salaries, you could simply do:
using (var transaction2 = instance.BeginTransaction())
{
foreach (var e in employees)
{
e.Salary = CalculateSalary(e);
}
transaction2.Commit();
}
As you can see, there's no need to call Manage again, you just have to set whatever properties you want to update within a write transaction.
Related
Trying to update a list of Incident records. The first one in the foreach updates, the next one throws an exception stating "the context is not currently tracking the incident entity". Is this the correct way to code this?
var openCases = (from o in xrmContext.IncidentSet
where o.StateCode == 0
select o).Take(5).ToList();
foreach (var c in openCases)
{
var numDays = ((TimeSpan) (DateTime.Now - c.CreatedOn)).Days;
Console.WriteLine("case age: {0}, case number:{1}", numDays, c.TicketNumber);
c.new_caseage = numDays;
xrmContext.UpdateObject(c);
xrmContext.SaveChanges();
}
When you call SaveChanges() it, in addition to saving any modified entity records, detaches all entity records being tracked in the context. Therefore, the second time you call SaveChanges() the entity record is not being tracked and you receive the error.
You should move the xrmContext.SaveChanges(); line to be after the foreach loop.
var openCases = (from o in xrmContext.IncidentSet
where o.StateCode == 0
select o).Take(5).ToList();
foreach (var c in openCases)
{
var numDays = ((TimeSpan) (DateTime.Now - c.CreatedOn)).Days;
Console.WriteLine("case age: {0}, case number:{1}", numDays, c.TicketNumber);
c.new_caseage = numDays;
xrmContext.UpdateObject(c);
}
xrmContext.SaveChanges();
All entities are detached by the OrganizationServiceContext after calling the SaveChanges method. To continue using the data context against previously retrieved entities, the entities need to be reattached.
However, the preference is to apply all modifications under a single call to SaveChanges, and then dispose the context, to avoid the need to reattach.
http://msdn.microsoft.com/en-us/library/gg695783.aspx
http://msdn.microsoft.com/en-us/library/gg334504.aspx#track_related
A better way to do what your try to do is using the message ExecuteMultipleRequest, with it can configure how many record to process for every iteration (internal iteration)
var openCases = (from o in xrmContext.IncidentSet
where o.StateCode == 0
select o).Take(5).ToList();
var requestWithResults = new ExecuteMultipleRequest()
{
// Assign settings that define execution behavior: continue on error, return responses.
Settings = new ExecuteMultipleSettings()
{
ContinueOnError = false,
ReturnResponses = true
},
// Create an empty organization request collection.
Requests = new OrganizationRequestCollection()
};
foreach (var c in openCases)
{
var numDays = ((TimeSpan) (DateTime.Now - c.CreatedOn)).Days;
c.new_caseage = numDays;
CreateRequest createRequest = new CreateRequest { Target = c };
requestWithResults.Requests.Add(createRequest);
}
ExecuteMultipleResponse responseWithResults =
(ExecuteMultipleResponse)_serviceProxy.Execute(requestWithResults);
Hope it helps
I have an object that has a many-to-many relationship with another object. I am trying to write an update statement that doesn't result in having to delete all records from the many-to-many table first.
My data is:
StoredProcedure - StoredProcedureId, Name
Parameter - ParameterId, Name
StoredProcedure_Parameter - StoredProcedureId, ParameterId, Order
I have a UI for updating a stored procedured object (adding/removing parameters or changing the order of the parameters).
When I save, I end up at:
var storedProcedure = context.Sprocs.FirstOrDefault(s => s.SprocID == sproc.StoredProcedureId);
if (storedProcedure == null)
{
//do something like throw an exception
} else
{
storedProcedure.Name = sproc.Name;
//resolve Parameters many to many here
//remove all Params that are not in sproc.Params
//Add any params that are in sproc.Params but not in storedProcedure.Params
//Update the Order number for any that are in both
}
I know I could simply call .Clear() on the table and then reinsert all of the values with their current state (ensuring that all parameters that were removed by the UI are gone, new ones are added, and updated Orders are changed). However, I feel like there must be a better way to do this. Do many-to-many updates with EF usually get resolved by deleting all of the elements and reinserting them?
Here there is my code that I use and it works. The difference is that instead o having your 3 tables( StoredProcedure, StoredProcedure_Parameter and Parameter ) I have the following 3 tables: Order, OrdersItem(this ensure the many-to-many relation) and Item. This is the procedure that I used for updating or add an order, or after I change an existing OrderItem or add a new one to the Order.
public void AddUpdateOrder(Order order)
{
using (var db = new vitalEntities())
{
if (order.OrderId == 0)
{
db.Entry(order).State = EntityState.Added;
}
else
{
foreach (var orderItem in order.OrdersItems)
{
if (orderItem.OrderItemsId == 0)
{
orderItem.Item = null;
if (order.OrderId != 0)
orderItem.OrderId = order.OrderId;
db.Entry(orderItem).State = EntityState.Added;
}
else
{
orderItem.Order = null;
orderItem.Item = null;
db.OrdersItems.Attach(orderItem);
db.Entry(orderItem).State = EntityState.Modified;
}
}
db.Orders.Attach(order);
db.Entry(order).State = EntityState.Modified;
}
SaveChanges(db);
}
}
The Lucene.Net.Linq project seems pretty powerful and while querying seems pretty simple, I'm not quite sure how to add/update documents. Can an example or two be provided?
There are some full examples in the test project at https://github.com/themotleyfool/Lucene.Net.Linq/tree/master/source/Lucene.Net.Linq.Tests/Samples.
Once you've configured your mappings and initialized your provider, you make updates by opening a session:
var directory = new RAMDirectory();
var provider = new LuceneDataProvider(directory, Version.LUCENE_30);
using (var session = provider.OpenSession<Article>())
{
session.Add(new Article {Author = "John Doe", BodyText = "some body text", PublishDate = DateTimeOffset.UtcNow});
}
You can also update existing documents. Simply retrieve the item from the session, and the session will detect if a modification was made:
using (var session = provider.OpenSession<Article>())
{
var item = session.Query().Single(i => i.Id == someId);
item.Name = "updated";
}
Or you can delete documents:
using (var session = provider.OpenSession<Article>())
{
var item = session.Query().Single(i => i.Id == someId);
session.Delete(item);
}
When the session is disposed, all pending changes in the session are written to the index and then committed. This is done within a synchronization context to ensure all changes in the session are committed and seen atomically when queries are being executed on other threads.
i am developing an application in mvc3.
I have two dropdowns and on the basis of value selected in first dropdown the second dropdown is populated.
The first dropdown is Course and on the basis of course selected the second dropdown populates the states where the course is available.
Foreg.if the course is 'MCA' the states should be Maharashtra,rajasthan and so-on.
For this i have written an ajax function which is working fine.
But the problem is i am not able to fetch multiple states at a time that is i can fetch only One state at a time.
I have written the following Code to fetch the state name:
HobbyHomeAdress Table contains ProvincialStateID which i fetch through some other method.
Then i compare that value with the value in ProvincialStateID in ProvincialState Table and fetch the data of that table but with it gives me the last record only.
public ICollection<ProvincialState> FetchStateByStateid(ICollection<HobbyHomeAddress> hobbyhomeaddresslist)
{
log.Debug("Start");
ISession session = DataAccessLayerHelper.OpenWriterSession();
ITransaction transaction = session.BeginTransaction();
ICollection<ProvincialState> provincialstate = null;
try
{
foreach (var state in hobbyhomeaddresslist)
{
provincialstate = session.CreateCriteria(typeof(ProvincialState))
.Add(Expression.Eq("ProvincialStateID", state.ProvincialState.ProvincialStateID))
.List<ProvincialState>();
}
transaction.Commit();
}
catch (SessionException ex)
{
if (transaction != null && transaction.IsActive)
transaction.Rollback();
log.Error(ex);
provincialstate = null;
}
finally
{
if (transaction != null)
transaction.Dispose();
if (session != null && session.IsConnected)
session.Close();
log.Debug("End");
}
return provincialstate;
}
you are recreating the provincialstate collection for each state in hobbyhomeaddresslist. So you end up with a collection with a single entry, usually the last one. Instead you should create the collection upfront and after retrieving an item, just add it to that collection.
...snip
...
List<ProvincialState> provincialstate = new List<ProvincialState>();
try
{
foreach (var state in hobbyhomeaddresslist)
{
var list = session.CreateCriteria(typeof(ProvincialState))
.Add(Expression.Eq("ProvincialStateID", state.ProvincialState.ProvincialStateID))
.List<ProvincialState>();
provincialstate.AddRange(list);
}
transaction.Commit();
}
...
Update: single query using a Disjunction.
IList<ProvincialState> provincialstate = null;
Disjunction dj = new Disjunction();
try
{
foreach (var state in hobbyhomeaddresslist)
{
dj.Add(Expression.Eq("ProvincialStateID", state.ProvincialState.ProvincialStateID));
}
provincialstate = session.CreateCriteria(typeof(ProvincialState))
.Add(dj)
.List<ProvincialState>();
transaction.Commit();
}
if you look at the generated SQL, you should now see a single select with several where clauses instead of several selects with a single where clause.
I am trying to merge data between two identical schema databases using Linq-to-sql:
List<Contact> contacts = (from c in oldDb.Contact
select c).ToList();
contacts.ForEach(c => c.CreatedByID = 0);
newDb.Contact.InsertAllOnSubmit(contacts);
newDb.SubmitChanges();
Merely throws an "An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext. This is not supported." exception.
Other than doing the following, how else can this be done generically (in reasonable execution time):
List<Contact> contacts = (from c in oldDb.Contact
select c).ToList();
contacts.ForEach(c => { c.CreatedByID = 0; newDb.Contact.InsertAllOnSubmit(contacts); });
newDb.SubmitChanges();
along with:
private t GetNewObject<t>(t oldObj)
{
t newObj = (t)System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(typeof(t).Name);
PropertyInfo[] props = typeof(t).GetProperties();
foreach (PropertyInfo _prop in props)
{
_prop.SetValue(newObj, _prop.GetValue(oldObj, null), null);
}
return newObj;
}
The problem is this method is rather slow when there's only 11 objects and 75 properties, I need to do this for a couple hundred thousand objects so any performance gains I can get at this end would greatly reduce overall run time.
Basically, is there any Detach or similar call I could do that will disconnect the existing objects from the old DataContext and connect them to the new DataContext. Without having to create all new objects for each and every one of the returned rows.
I didnt got the
contacts.ForEach(c => { c.CreatedByID = 0; newDb.Contact.InsertAllOnSubmit(contacts); });
shouldnt be something like
contacts.ForEach(c => {
Contact c2 = GetNewObject<Contact>(c);
c2.CreatedByID = 0;
newDb.Contact.InsertOnSubmit(c2);
});
also, here's a way of detaching the object from the old database: http://omaralzabir.com/linq_to_sql__how_to_attach_object_to_a_different_data_context/