Disable Lazy-Load Entity Framework Navigation Properties - multithreading

Question
Is there any way to make it so that an entity returned from a DbContext query returns null (or some other specific value) when you try to access a navigation property that you did not specificly .Include()? For example:
var parents = dbContext.People.Where(p => p.Children.Any()).Include("Children").ToList();
//Assert all parents have children...
Assert.IsTrue(parents[0].Children.Any());
And...
var parents = dbContext.People.Where(p => p.Children.Any()).ToList();
//Assert all children collections are null... NOT LAZY LOADED
Assert.IsTrue(parents[0].Children == null);
To be clear, I do not want the property to be Eager-Loaded. I don't want it to be loaded at all. I've tried Detaching the entity from the context, but this doesn't help.
Background
The reason I am trying to do this is because i need to access the entity object on a diffrent thread than the one the DbContext was created on. Because of this, I do NOT want the navigation property to be set to some defered excution linq statement. The problem is that since I cannot access DbContext to check if a navigation property is loaded or not (due to it not being thread safe) I have no way of knowing if I need to create a new DbContext on the current thread to retrieve the missing data. This is the same problem that I was trying to solve with How to tell if a Navigation Property is loaded without DbContext
Update
Setting the DbContext's Configuration.LazyLoadingEnabled property to false prevents the linq from getting auto-wired up, but for navigation properties that are collections this results in a empty collection rather than null.
To solve the collection based problem, I Modified my T4 template to generate an empty default constructor rather than one that set each ICollection equal to an empty HashSet.

You can enable / disable lazy-loading by setting the Configuration.LazyLoadingEnabled property of your DbContext
context.Configuration.LazyLoadingEnabled = false;
var parents = dbContext.People.Where(p => p.Children.Any()).ToList();
context.Configuration.LazyLoadingEnabled = true;

Related

How to set Media Url of MediaPart? Orchard MediaLibraryPickerField MediaParts is null

I am trying to automatically assign the MediaPart.MediaUrl to a custom image upon published. But..
MediaPickerField MediaParts is always null.
OnPublished<BlogPostPart>((context, part) =>
{
ContentPart cp = part.ContentItem.Parts.Skip(13).First();
MediaLibraryPickerField field = cp.Fields.FirstOrDefault() as MediaLibraryPickerField;
if (field != null) {
// this part throws an object null reference exception since fields.MediaParts is null
foreach(Orchard.MediaLibrary.Models.MediaPart mp in field.MediaParts){
}
}
});
How to programically set the MediaUrl from the code on the event on publish? I am using Orchard 1.8
MediaParts is implemented as a lazy field so that the value isn't fetched unnecessarily. The loader for the lazy field is set-up by the handler for the field, during the Loaded event.
A content item that has just been created has gone through Creating, Created, and Publishing before it goes into Published. That means that the media library picker fields's media part collection is not available at this point.
What is it exactly that you're trying to do?
Also, you should never rely on the order or number of parts on a content item, so that Skip(13) is not the right way of getting to the part you want.

ViewModel for nested control not refreshing in Catel MVVM for WPF

I have a nested control (NC1) which contains 3 instances of NC2. When the containing view is first opened, NC1 will be null and so the three instances of NC2 will be null. This appears to work correctly based on debugging through my code and the framework.
When a selection is made in the containing view NC1 is properly set (and the ViewModel is (re)created) and values for its properties (exposed through Fody.Expose) appear in the view. However, none of the ViewModels for NC2 are (re)created and they do not reflect the values provided by their respective models.
I am not sure exactly what information to provide without uploading a lot of content, so I will take a stab.
In the NC1 view, I have the following
<localViews:NC2 DataContext="NC2Entry1"/>
<localViews:NC2 DataContext="NC2Entry2"/>
<localViews:NC2 DataContext="NC2Entry3"/>
NC2EntryX are properties on the NC1 ViewModel that return a specific instance of an NC2 model from a list. The NC2EntryX properties is NOT registered with RegisterProperty.
As a note, I have discovered that I must have an empty parameter constructor for the NC1 and NC2 view models. If I do not, then I receive a MissingMethod exception when the view model is being created when the TypeFactory attempts to create the ViewModel with the Activator instead of using the injection path. The injection path is not used because the call at line 591 of TypeFactory returns false because the NC2 model passed is 'not registered'. (Not sure if it should be or how to make it so.)
I am using Catel version 3.9.0
The NC2EntryX property changes must be reflected to the view somehow. You can do this by making it Catel properties, or by calling RaisePropertyChanged("NC2EntryX") yourself when setting the property value. Only in that case the view will be updated (this is just standard WPF / MVVM behavior).
About the missing method exception: it is a first chance exception where the TypeFactory tries to fall back to Activator.CreateInstance when it fails to create the type with dependency injection. No need to worry about this. If you don't want view models to be alive without a model, don't create an empty constructor.

Seam page actions and conversation

I have created my application using seam-gen. Seam-gen has created all the crud operations & forms for all my objects. They all inherit from seam's EntityHome.
I have this requirement that I need to create from an object A another object B (A has a List). So I need to redirect the user to the B form, save a new B object, and then redirect him to the original A form with the updated List contents.
I am a newbie in Seam and I am not sure how to implement this properly.
Edit: I am using seam version 2.2.2 final.
You can create an action class (similar to how entityHome works without the baggage that comes with it) to manage your contained entities and their behaviors. If no relationship exists between the entities you can make one here.
Refreshing the original list can be tricky, but once you have some code started post it.
So I would start with something like:
Class ActionBean {
ClassAObj classA;
List<ClassBObj> classBList;
public void methodThatLinksAandB() {
// ... stuff happens here
}
// getters and setter for view
// private worker methods
}

MvvmCross indexed property bind not getting changes from view

I have a list on my view model that contains an object and property that I am trying to bind to from the main view.
var field = new UITextField();
Add(field);
this.AddBindings(
new Dictionary<object, string>()
{
{ field, "Text Names[0].Value" }
}
);
This will load fine and display the initial value from the view model but won't receive any values back when UITextField.Text is modified. It seems like it is not 2 way. Value is not a notification property but could be made into one if that is what this setup requires.
I also tried the following but that does work at all:
set.Bind(field).To(vm => vm.Names[0].Value);
Using MvvmCross 3.0.9. Xamarin.iOS 6.3.7
I've just tested this using 3.0.9 with a ViewModel which has an ObservableCollection of non-INPC Thing objects and this two way binding seems to work OK for me - both when the ObservableCollection changes and when the UITextField value changes because of user action.
Can you provide any more of your ViewModel nad list object code? (If not, can you reproduce the error in a simple sample?)
Can you provide any error trace you are seeing (in debug|output)? (This may need enabling - see MvvmCross Mvx.Trace usage)
Can you provide any more information on the form that "does work at all" - this might be a clue about what is going wrong.

EF4 Self tracking entities navigation property

I'm using EF4 with Self Tracking Entities T4 template.
When I perform a select on entity Page (with navigation property Category) like:
var page = (from p in context.Page select p).FirstOrDefault();
The navigation property Category is always null.
When I do it like this:
var page = (from p in context.Page.Include("Category") select p).FirstOrDefault();
The Category is loaded.
Why do I have to use the include function with a hardcoded string? Is it not possible to have EF4 automatically load the navigation property when I access it?
Or does that only work with EntityObjects and not STE?
STE does not support lazy loading, only through context.LoadProperty. POCO + EntityObject do support it.
.Include is for eager loading, hopefully this method will be changed to support lambda expressions instead of hardcoded string.

Resources