A few MVVM and Entity Framework questions

  • Thread starter Thread starter --
  • Start date Start date
?

--

I've been out of the .NET game for a few years now [pre 2005] and
starting a little project using the Entity Framework and WPF. My
understanding is that the MVVM pattern is the way to go nowadays, but
I've got a few questions.
This is a purely made up example, so forgive any UI design quirks, and
I'm leaving out a bunch of code just as the INotifyPropertyChanged
stuff.

1. Let's say I've got a heavy-ish model class called Report. I'd like
to create a Report browser type of viewer. I'd like the browser to
have a combobox / listbox / treeview / something where the user can
select the report to view, and a Report User Control that displays the
currently selected report. In all the examples I've seen, the
ReportBrowserViewModel would collection of Reports or ReportViewModels
which is bound to the combobox/listbox/treeview. Something like this:
ReportViewModel
{
ObervableCollection<Report> Reports;
}

The Report User Control's DataContext is a ReportViewModel which is
bound to the current ReportViewModel as set by the
ObservableCollections CurrentItem [I can't figure out how to get this
in code, just in the XAML].

I'd like to not have to bring all the Reports into memory [they're
heavy], so I'd like to just bring in a ReportHeader, which is a subset
of the Report data. In doing so, my ReportBrowserViewModel would look
something like this:
ReportBrowserViewModel
{
ObservableCollection<ReportHeader> ReportHeaders;
ReportViewModel CurrentReport;
}

I'd like the combobox/listbox/treeview to be bound to the
ReportHeaders, and when the ReportHeader's CurrentItem changes, I'd
like to set the CurrentReport to the appropriate Report [in doing so,
updating the bound ReportUserControl]

Is this how it's supposed to be done? If so, this leads to question 2.

2. In the above scenario, the ReportBrowserViewModel would need to get
a Report to fill the ReportViewModel. Is it appropriate for the
ReportBrowserViewModel to access the DAL to get the Report? If not,
how should the Report be obtained?
2a. In general, how is data supposed to be loaded into the ViewModel?
Something has to put the Model objects into the ViewModel. In my
example, should I load the ReportHeader via the Window, or have them
passed in?

3. Commands. Are Model modifying commands supposed to be placed in
the ViewModel? Things like adding a line item to a report? So I'd have
a Command:
AddLineItemToReportCommand : ICommand
{
public AddLineItemToReportCommand(Report report);
....
}
and the ReportViewModel would have a property:
AddLineItemToReportCommand addLineItem;
AddLineItemToReportCommand AddLineItem
{
get{
addLineItem = addLineItem ?? new
AddLineItemToReportCommand(this.Model);
addLineItem = addLineItem.Model == this.Model
? addLineItem
: new
AddLineItemToReportCommand(this.Model);
return addLineItem;
}
}
This would be creating a new Command instance every time the Model in
the ReportViewModel changes? This seems like a lot.

4. A more general generics question. If I have a generic class:
B<T> : INotifyPropertyChanged
{
T item;
T Item{
get{return item;}
set{
if(item==value)return; // Note, this doesn't work
item=value;
OnPropertyChanged("Item");
}
}
}
What's the appropriate method in the setter for checking if the new
value is equal to the old value? == doesn't work unless there's a
class constraint on T, and item.Equals(value) will throw an exception
in item or value are null. My current method is:
if(item == null && value == null)return;
if(item==null || value==null || !item.Equals(value))
{
item=value;...
}
But this seems excessive. There must be a better way.
 
Hello,

First of all I'm starting with MVVM...
I'd like to not have to bring all the Reports into memory [they're
heavy], so I'd like to just bring in a ReportHeader, which is a subset
of the Report data. In doing so, my ReportBrowserViewModel would look
something like this:
ReportBrowserViewModel
{
ObservableCollection<ReportHeader> ReportHeaders;
ReportViewModel CurrentReport;
}

Not sure which kind of report is this ? IMO just expose a list of reports
(perhaps your own type). You could likely lazy load the actual report when
it is used. Not sure which kind of reports. YOur UI won't have any idea
about reports being lazy loaded...
2. In the above scenario, the ReportBrowserViewModel would need to get
a Report to fill the ReportViewModel. Is it appropriate for the
ReportBrowserViewModel to access the DAL to get the Report? If not,
how should the Report be obtained?

Perhaps rather the "Model" assuming the "DAL" is the really low level data
access layer. Not sure which store you are using. Also you are using MVVM
for benefits, not for the sake of using it. So if you don't see any interest
to have something in between just access your "DAL" whatever it is
actually...
2a. In general, how is data supposed to be loaded into the ViewModel?
Something has to put the Model objects into the ViewModel. In my
example, should I load the ReportHeader via the Window, or have them
passed in?

IMO ReportHeaders should be loaded by ReportBrowserViewModel as needed (for
example at load time seems sensible, you could lazy load by exposing a
property rather than a field. Once agin it can change without any concern
....
3. Commands. Are Model modifying commands supposed to be placed in
the ViewModel? Things like adding a line item to a report? So I'd have
a Command:
AddLineItemToReportCommand : ICommand
{
public AddLineItemToReportCommand(Report report);
...
}
and the ReportViewModel would have a property:
AddLineItemToReportCommand addLineItem;
AddLineItemToReportCommand AddLineItem
{
get{
addLineItem = addLineItem ?? new
AddLineItemToReportCommand(this.Model);
addLineItem = addLineItem.Model == this.Model
? addLineItem
: new
AddLineItemToReportCommand(this.Model);
return addLineItem;
}
}
This would be creating a new Command instance every time the Model in
the ReportViewModel changes? This seems like a lot.

Expose the command as a property and create the command as needed (using a
private member)...
4. A more general generics question. If I have a generic class:
B<T> : INotifyPropertyChanged
{
T item;
T Item{
get{return item;}
set{
if(item==value)return; // Note, this doesn't work
item=value;
OnPropertyChanged("Item");
}
}
}
What's the appropriate method in the setter for checking if the new
value is equal to the old value? == doesn't work unless there's a
class constraint on T, and item.Equals(value) will throw an exception
in item or value are null. My current method is:
if(item == null && value == null)return;
if(item==null || value==null || !item.Equals(value))
{
item=value;...
}
But this seems excessive. There must be a better way.

If coded one time it"s fine with me. My personal preference would be perhaps
to use overload rather than generics (not sure how you plan using this but
using always "item" doesn't seems convenient ??!!) as usually you only needs
this agains few types rather than against arbitrary types....
 
Hello,

First of all I'm starting with MVVM...
I'd like to not have to bring all the Reports into memory [they're
heavy], so I'd like to just bring in a ReportHeader, which is a subset
of the Report data.  In doing so, my ReportBrowserViewModel would look
something like this:
ReportBrowserViewModel
{
    ObservableCollection<ReportHeader> ReportHeaders;
    ReportViewModel CurrentReport;
}

Not sure which kind of report is this ? IMO just expose a list of reports
(perhaps your own type). You could likely lazy load the actual report when
it is used. Not sure which kind of reports. YOur UI won't have any idea
about reports being lazy loaded...
Report is just a generic term I'm using for the classes I'm dealing
with. Just imagine an class where I don't want all the instances
loaded in memory the whole time [so I don't want to just load the full
reports and browse through them]. The way I understand it, I can
lazily load associations, but not individual scalar values, so I can't
load partial reports. I suppose I could have a ReportHeaderEntity
that has an association with a full report and dynamically load the
report, but then questions remain able keeping the objects in sync.
Perhaps rather the "Model" assuming the "DAL" is the really low level data
access layer. Not sure which store you are using. Also you are using MVVM
for benefits, not for the sake of using it. So if you don't see any interest
to have something in between just access your "DAL" whatever it is
actually...
I'm using the Entity Framework stuff, so the DAL is the ObjectContext.
Should I just think of this as part of the Model and not a separate
layer? If so, some of these questions / concerns go away.
IMO ReportHeaders should be loaded by ReportBrowserViewModel as needed (for
example at load time seems sensible, you could lazy load by exposing a
property rather than a field. Once agin it can change without any concern
...

So the ReportBrowserViewModel would have an instance of the
ObjectContext for managing the Reports and ReportHeaders?
Expose the command as a property and create the command as needed (using a
private member)...
Got it, that's the approach I'm taking in my example.
If coded one time it"s fine with me. My personal preference would be perhaps
to use overload rather than generics (not sure how you plan using this but
using always "item" doesn't seems convenient ??!!) as usually you only needs
this agains few types rather than against arbitrary types....
To me, generics overcome the problem of having to rewrite the same
functions over and over again for different types. In the example I
gave, Item is just a term I'm using to illustrate the question. The
actual property name is not Item. The same problem comes up any time
you try to compare two instances of an unspecified generic. I'm trying
to figure out the appropriate way to handle that.
 
Report is just a generic term I'm using for the classes I'm dealing
with. Just imagine an class where I don't want all the instances
loaded in memory the whole time [so I don't want to just load the full
reports and browse through them]. The way I understand it, I can
lazily load associations, but not individual scalar values, so I can't
load partial reports. I suppose I could have a ReportHeaderEntity
that has an association with a full report and dynamically load the
report, but then questions remain able keeping the objects in sync.

My first though was that it was some some reports as those produced using a
reporting tools. Now my understanding is that they are just entities loaded
from the database.

AFAIK you could do this using :
http://msdn.microsoft.com/en-us/library/bb738443.aspx (Table Per Hierarchy
Inheritance).

It would allow to have a baseentity that just have the basic properties for
the report and an inherited type that have all the properties (I assume the
part you want to lazy load are blob values).

You could likely also have your ViewModel to load selected columns from the
reports but still using the report type. So the blob column will be just
empty. Then at a later time you'll lazy load the remaining column. Here you
do that manually but as your model is hidden from the view using the
ViewModel it doesn't matter...
I'm using the Entity Framework stuff, so the DAL is the ObjectContext.
Should I just think of this as part of the Model and not a separate
layer? If so, some of these questions / concerns go away.

Depends, if you want to be able to test your ViewModel against other data
you could use an interface to be able to replace the actual Model with a
mock...
To me, generics overcome the problem of having to rewrite the same
functions over and over again for different types.

IMO PropertyChanged tends to be used always for the same few primitive
types.

In the example I
gave, Item is just a term I'm using to illustrate the question. The
actual property name is not Item. The same problem comes up any time
you try to compare two instances of an unspecified generic. I'm trying
to figure out the appropriate way to handle that.

OK I believe I might have taken your code sample too literally. Perhaps in
the worst case a version with a struct constraint and a version with a class
constraint (you really need this one ?)

Something like :

static void OnStructChanged<T>(T currentValue,T newValue) where T:struct
static void OnClassChanged<T>(T currentValue,T newValue) where T:class

It would bne perhaps nice to be able to do something like
T.Equals(currentValue,newValue) in generics. Don't think it is currently
possible.

Please, let me know if you find some interesting architecture resource...
 
Didn't had time to give this a closer look but I found a thread on another
subject that suggests using something such as :

EqualityComparer<T>.Default.Equals(currentValue,newValue)

It would allow to do the comparison by using the static method and could be
a clean replacement for the null issue (if this is really an issue)...
 
-- said:
[...]
What's the appropriate method in the setter for checking if the new
value is equal to the old value? == doesn't work unless there's a
class constraint on T, and item.Equals(value) will throw an exception
in item or value are null. My current method is:
if(item == null && value == null)return;
if(item==null || value==null || !item.Equals(value))
{
item=value;...
}
But this seems excessive. There must be a better way.

As I mentioned before, I can't really help much with the MVVM stuff.
However, as far as your generics question goes…

The static System.Object.Equals() method does basically what you're
doing above. So your method could just look like this:

T Item
{
set
{
if (!object.Equals(item, value))
{
item = value;
}
}
}

Pete
 
Didn't had time to give this a closer look but I found a thread on another
subject that suggests using something such as :

EqualityComparer<T>.Default.Equals(currentValue,newValue)

It would allow to do the comparison by using the static method and could be
a clean replacement for the null issue (if this is really an issue)...

Thanks! This is exactly the type of thing I was looking for.
 
IMO PropertyChanged tends to be used always for the same few primitive
types.

By constrast List<T> is likely used against hundreds if not thousands or
millions of types if you take enough code samples around the earth...

Imagine a scenario where I've got a wrapper type of class that I want
to emit an PropertyChanged event when I set or change in the inner
item, like the inner Model in a ViewModel (to keep with the MVVM
theme). I find this type of situation occurring a lot.
 
Back
Top