Re-Use object added to EF - c#

I am using EF 4. I want to add a row to a (message) table, so I declare a new object (newMSG), and populate it. Then I use the message table's method .AddObject(newMSG) to add the new row.
Is the newMSG object now available to "re-use" to add another row? Or do I need to have a new object? Seems like I should be able to re-use the newMSG object, but it's not so easy to test.
You guys'll know right off the bat... Of course, this would apply to any object, I assume. There's nothing special about EF....
Does it matter perhaps if I use the savechanges() method between uses?

You need a new object. There is metadata attached to that newMSG object that ties it to that particular row.

Related

Acumatica Customization - How to remove anonymous delegate from PXGraph.RowInsertingEvents Collection?

I‘m working on customization that involves adding extra Sales Person transactions when Cancelling/Correcting an Invoice. As part of the development effort, I have identified that the common method that’s called by both the processes – Cancel Invoice and Correct Invoice, is ReverseDocumentAndApplyToReversalIfNeeded in the Graph PX.Objects.AR.ARInvoiceEntry.
I have the custom code to add new salespersons to the ARInvoiceEntry.salesPerTrans view but when I do after ReverseDocumentAndApplyToReversalIfNeeded runs, I see that my code doesn’t insert the new records to the view and doesn’t give any error. After much troubleshooting, I’ve found out that there’s a line of code in the method ReverseInvoiceProc of ARInvoiceEntry.cs that stops from inserting a new row. Here’s that line of code:
this.RowInserting.AddHandler<ARSalesPerTran>((sender, e) => { e.Cancel = true; });
It’s an anonymous delegate that’s added.
I would like to know how can I get hold of this anonymous handler in my custom code so that I can:
Remove that anonymous handler
Do my custom logic of adding new rows
Add the anonymous delegate back to the RowInsertingEvents list
I tried to look in the Acumatica code repository but couldn’t find anything that would help me remove anonymous delegate. What I can find was the removal of named handlers, like the below example:
APPaymentEntry pe = CreateInstance<APPaymentEntry>();
pe.RowSelecting.RemoveHandler<APPayment>(pe.APPayment_RowSelecting);
So please let me know how can I dynamically remove that anonymous handler from within my custom code. I have reference to the ARInvoiceEntry graph through the Base property of my extension graph. If you can redirect me to a specific page in the Acumatica Code repository, that would work as well.
I do not think you could remove this anonymous method from there in a easy way.
However, one approach you could implement is to override the "ReverseDocumentAndApplyToReversalIfNeeded" method and call base method there.
After this you could create a new instance of the ARinvoiceEntry graph (in that same override after calling base method), select the primary record(header) and then try to make your second insert ( this way to avoid the ReverseInvoiceProc.)

Create entry if one does not exist

I'm trying to create a single instance of a model in my Db using Entity Core. The way I want it to work is, if the entry in the Db does not exist than make one. Instead of writing a getter method to do the work, is it possible to have Entity Core generate me a blank entry to work with and the save back?
I tried using FirstOrDefault to no avail.
Here is some sample code:
using (var context = new SearchTermInformationContext())
{
// this very first line should return me the single instance or create one if it doesnt exist.
var searchTermInfo = context.SearchTermInformation.FirstOrDefault();
searchTermInfo.num_search_terms += numSearchTerms;
searchTermInfo.offset = offset;
searchTermInfo.last_updated += (DateTime.UtcNow.Ticks / TimeSpan.TicksPerMillisecond).ToString();
await context.SaveChangesAsync(ct);
}
FirstOrDefault() grabs the first element of an IEnumerable, and if the sequence is empty it returns the default value for that type. Since an Entity is always going to be a class, the default "value" for any class is null. There is no way to my knowledge to change this behavior. If you want this behavior, you will have to implement it yourself by creating a new instance of your type, filling in the fields, and performing an insert through your context. If you want to get really fancy, you might be able to make an extension method on DbSet<T> to perform an add of a blank instance and return the attached entity without saving changes.

Serialization of only changed members

I am new to MongoDB and want to serialize my object efficiently. That means when updating an object i want only to write the fields that changed. If my object has sub objects in a list, i only want to add or remove the changed sub objects. That is because if i have a post with 1000 comments i want to avoid to serialize the whole object each time a new post comes around.
all i found is the convention ignoreifempty, ignoreisdefault and the shouldserializexyz pattern.
is it possible to write a convention like ignoreifnotchanged (i track the dirty fields in my objects) or is there a more general shouldserializexyz because i don't want to write the method for every property.
What you want to look into is the Update method with an update argument that specifies which fields you want to update.
You can use the Update builder to build the update argument value. Look into:
Update.Set(name, value)
Update.Push(name, value)
(there are many more also).
You can chain Update methods together to update more than one field at a time.
There is currently no built in change tracking, so you would have to keep track of which fields have changed yourself, and build the update argument based on your knowledge of what changed.
There is also a pending JIRA feature request that is related to this. See:
https://jira.mongodb.org/browse/CSHARP-237
Please comment or vote on the JIRA if you want.

Populating A New Object With Existing Objects Data

I have a service that is returning a custom object called "UserSettings" In my application I want to add more properties to the "UserSettings" object so I created a new object called "MyUserSettings" that inherits from "UserSettings" now I want to populate my new object with the existing data held in "UserSettings" and the new data I have for my new properties. I do not want to have to map each property one by one to the same property in the new object like this..
_MyUserSettings.Name=_UserSettings.Name;
Is there a way or better approach to what I am doing to populate ALL the properties of the existing object into my new object in one shot??
Yes, you can use Copy Constructor pattern. It would give you an other benefit - you do not need public property setters so object becomes immutable.
public MyUserSettings(UserSettings baseSettings)
{
// TODO: set all properties
}
Unfortunately this is the only way, however, the specific mechanism can change. There are a numerous ways (not listing them all):
Copy constructor, that takes an item and does this manual copying of fields across.
Use reflection to have a more generic mechanism of achieving the same.
Use something like AutoMapper.
They all boil down to pretty much doing the same thing.
If the UserSettings is actually a MyUserSettings then you can simply cast it:
var mySettings = (MyUserSettings)settings;
However, this will fail if UserSettings is really UserSettings.

C# - Using a copy of Session-stored variables instead of reference

I have an asp:ImageButton with OnClick="Btn_OnClick".
In Btn_OnClick I have this line:
DataTable dtTable = (DataTable)Session["someSessionKey"]
and dtTable is altered in the function.
I've noticed that if the button's clicked more than once, the dtTable I take from the session contains the altered table, probably meaning dtTable is not a copy but a reference of the session variable.
How can I alter a copy of Session["someSessionKey"], and not the actual value?
Thanks!
DataTable dtTable = ((DataTable)Session["someSessionKey"]).Copy();
If the object in the Session implements ICloneable, you can use var myCopy = mySessionObject.Clone();. You would then have to read the documentation of the object to see what it exactly does.
This is because there is no generic solution to cloning. Mostly, objects have other non-scalar objects as properties, so it always depends on the scenario if you need to clone those child objects too.
When you author your own class, you can always call the protected MemberwiseClone() method that is defined in System.Object to get a flat clone. You can then choose if you want to add some additional cloning logic and if you want to make it available for callers outside.
If the object in the Session is a List<T> or an IEnumerable<T>, you can do var myCopiedList = new List<T>(myListInSession);. Keep in mind that the individual objects in that list are not cloned in that case. You'd have to foreach through them and clone each object manually. It's similar with the DataTable. You might need to manually create a new instance and copy the content over.
To manually clone an object that doesn't support any public method to do so, you'd have to create a new instance of it. Then you'd assign every property from the original object to the cloned object manually. That can be not only tedious, often it also won't work because there are protected members that you can't access easily.
Finally, you can resort to reflection or other tricks to try to clone an object. A quick google search gave me that result: C# Object clone wars.

Categories