WPF / MVVM / EF - How to bind to an entity's related entities? - wpf

I have a detail view corresponding to a user entity. Each user entity has one or more comment entities, which is represented on the detail view as a grid.
So following EF convention, the user model has a UserComments member to represent the relation:
public partial class User
{
public int UserID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<UserComments> UserComments { get; set; }
//....
}
When it came time to create the user comments grid in the user detail view, I realized that the grid does not properly bind to an ICollection (couldn't add new rows to the grid). After some digging, I found that I needed to use an ObservervableColletion. Ok, so I converted my ICollection into an ObserverableCollection....
public class UserDetailViewModel
{
public virtual User UserData { get; set; }
private ObservableCollection<UserComments> _UserComments;
public ObservableCollection<UserComment> UserComments {
get { return _UserComments; }
}
public void Load(int UserID)
{
this.UserData = UserRepo.Find(UserID);
this._UserComments = new ObservableCollection<UserComment>(UserData.UserComments);
}
}
Cool. I can add rows to the grid now. But...
At this point, I've realized I've lost EF change tracking by converting User.UserComments to an ObservableCollection and have no easy way of getting the modifed/new comments back into EF.
So have I approached this all wrong? Is there a better way of updating the related data?

In order for EF to track collection changes, you need to be adding and removing from the collection in the model itself.
this._UserComments = new ObservableCollection<UserComment>(UserData.UserComments);
In the line above, you're creating a collection by copying elements, so when items are added to or removed from UserDetailViewModel.UserComments, those items aren't actually being added to or removed from User.UserComments.
Some options to fix this include:
Changing User.UserComments itself to an ObservableCollection and exposing that in the view model. For example:
public class UserDetailViewModel
{
public virtual User UserData { get; set; }
public ObservableCollection<UserComment> UserComments
{
get { return UserData.UserComments; }
}
// other stuff...
}
Handling add/remove events for UserDetailViewModel.UserComments and modifying the User.UserComments collection there.
This might be helpful as well:
https://msdn.microsoft.com/en-us/data/jj574514.aspx

Related

Has EF6+ / 7 added any ways that I can add update child tables?

I have two tables:
public AdminTest()
{
this.AdminTestQuestions = new List<AdminTestQuestion>();
}
public int AdminTestId { get; set; }
public string Title { get; set; }
public virtual ICollection<AdminTestQuestion> AdminTestQuestions { get; set; }
}
public partial class AdminTestQuestion
{
public int AdminTestQuestionId { get; set; }
public int AdminTestId { get; set; }
public System.Guid QuestionUId { get; set; }
public virtual AdminTest AdminTest { get; set; }
}
I am using the following EF6 code to add a new adminTest (with its adminTestQuestions) to the
database:
public async Task<IHttpActionResult> Post([FromBody]AdminTest adminTest)
{
db.AdminTests.Add(adminTest);
foreach (AdminTestQuestion adminTestQuestion in adminTest.AdminTestQuestions)
{
db.AdminTestQuestions.Add(adminTestQuestion);
}
await db.SaveChangesAsync(User, DateTime.UtcNow);
return Ok(adminTest);
}
I have similar but more complicated code to deal with the case where questions are added or removed from the adminTest. All my code works but it would be very good if EF was able to do what I needed rather than my having to add many lines of code.
Can anyone tell me if there have been any changes to EF6 or if any changes are planned to EF7 that will allow it
has noted on the ef7 github they seams to have added some neat code that add primary key entity.
but it is still not clear as to if it will be a common thing for children collection in an entity.
Git hub Entity Framework Design Meeting Notes
but for EF6 you could use a Generic Repository to make all the work for you. (since you can't extend DbContext directly)
assuming db is a DbContext
you could use this -> : Accessing a Collection Through Reflection
then find all Property from a class T that contains ICollection<> and do a foreach on the item of the ICollection Property then do db.Set.Add(proprietyChild) on it
that would eliminate the need for always repeating the same add child to entity code.
some people already did implement a solution thou : Automated updates of a graph of deached entities

How to create proper ViewModel for a complex Model

I have a model that looks like this:
// Subclass 1
class A
{
public B PropB { get; set; }
}
// Subclass 2
class B
{
public List<A> PropA { get; set; }
}
// And finally Model
class Model
{
public List<A> PropA { get; set; }
public List<B> PropB { get; set; }
}
Lists A and B inside Model class have references to some elements of each other.
How should the proper ViewModel look like in this case?
If there were no cross-references, that would be just 2 ObservableCollections of sub-ViewModels, but I cannot manage the situation with the references. Should each sub-ViewModel contain a references to other sub-ViewModels?
Hope that's clear enough.
You might want to have a look at Catel. It allows you to lazy-load view models based on a model. This way, you can create endless chains of view models without having to specify them first.
So, when a view detects a specific model, it will automatically convert it into a view model and you are good to go. For more information, read the docs about the nested user controls problem.
Disclaimer: I am one of the developers of Catel

How would I model data that is heirarchal and relational in a document-oriented database system like RavenDB?

Document oriented databases (particularly RavenDB) are really intriguing me, and I'm wanting to play around with them a bit. However as someone who is very used to relational mapping, I was trying to think of how to model data correctly in a document database.
Say I have a CRM with the following entities in my C# application (leaving out unneeded properties):
public class Company
{
public int Id { get; set; }
public IList<Contact> Contacts { get; set; }
public IList<Task> Tasks { get; set; }
}
public class Contact
{
public int Id { get; set; }
public Company Company { get; set; }
public IList<Task> Tasks { get; set; }
}
public class Task
{
public int Id { get; set; }
public Company Company { get; set; }
public Contact Contact { get; set; }
}
I was thinking of putting this all in a Company document, as contacts and tasks do not have a purpose out side of companies, and most of the time query for a task or contacts will also show information about the associated company.
The issue comes with Task entities. Say the business requires that a task is ALWAYS associated with a company but optionally also associated with a task.
In a relational model this is easy, as you just have a Tasks table and have the Company.Tasks relate to all tasks for the company, while Contact.Tasks only show the tasks for the specific Task.
For modeling this in a document database, I thought of the following three ideas:
Model Tasks as a separate document. This seems kind of anti-document db as most of the time you look at a company or contact you will want to see the list of tasks, thus having to perform joins over documents a lot.
Keep tasks that are not associated with a contact in the Company.Tasks list and put tasks assocaited with a contact in the list for each individual contacts. This unfortunately means that if you want to see all tasks for a company (which will probably be a lot) you have to combine all tasks for the company with all tasks for each individual contact. I also see this being complicated when you want to disassociate a task from a contact, as you have to move it from the contact to the company
Keep all tasks in the Company.Tasks list, and each contact has a list of id values for tasks it is associated with. This seems like a good approach except for having to manually take id values and having to make a sub-list of Task entities for a contact.
What is the recommended way to model this data in a document oriented database?
Use denormalized references:
http://ravendb.net/faq/denormalized-references
in essence you have a DenormalizedReference class:
public class DenormalizedReference<T> where T : INamedDocument
{
public string Id { get; set; }
public string Name { get; set; }
public static implicit operator DenormalizedReference<T> (T doc)
{
return new DenormalizedReference<T>
{
Id = doc.Id,
Name = doc.Name
}
}
}
your documents look like - i've implemented the INamedDocument interface - this can be whatever you need it to be though:
public class Company : INamedDocument
{
public string Name{get;set;}
public int Id { get; set; }
public IList<DenormalizedReference<Contact>> Contacts { get; set; }
public IList<DenormalizedReference<Task>> Tasks { get; set; }
}
public class Contact : INamedDocument
{
public string Name{get;set;}
public int Id { get; set; }
public DenormalizedReference<Company> Company { get; set; }
public IList<DenormalizedReference<Task>> Tasks { get; set; }
}
public class Task : INamedDocument
{
public string Name{get;set;}
public int Id { get; set; }
public DenormalizedReference<Company> Company { get; set; }
public DenormalizedReference<Contact> Contact { get; set; }
}
Now saving a Task works exactly as it did before:
var task = new Task{
Company = myCompany,
Contact = myContact
};
However pulling all this back will mean you're only going to get the denormalized reference for the child objects. To hydrate these I use an index:
public class Tasks_Hydrated : AbstractIndexCreationTask<Task>
{
public Tasks_Hydrated()
{
Map = docs => from doc in docs
select new
{
doc.Name
};
TransformResults = (db, docs) => from doc in docs
let Company = db.Load<Company>(doc.Company.Id)
let Contact = db.Load<Contact>(doc.Contact.Id)
select new
{
Contact,
Company,
doc.Id,
doc.Name
};
}
}
And using your index to retrieve the hydrated tasks is:
var tasks = from c in _session.Query<Projections.Task, Tasks_Hydrated>()
where c.Name == "taskmaster"
select c;
Which i think is quite clean :)
As a design conversation - the general rule is that if you ever need to load the child documents alone as in - not part of the parent document. Whether that be for editing or viewing - you should model it with it's own Id as it's own document. Using the method above makes this quite simple.
I'm new to document dbs as well...so with a grain of salt...
As a contrasting example...if you are on Twitter and you have a list of the people you follow, which contains a list of their tweets...you would not move their tweets into your twitter account in order to read them, and if you re-tweet, you would only have a copy, not the original.
So, in the same way, my opinion is that if Tasks belong to a company, then they stay within the Company. The Company is the Aggregate Root for Tasks. The Contacts can only hold references (ids) or copies of the Tasks and cannot modify them directly. If you have your contact hold a "copy" of the task, that's fine, but in order to modify the task (e.g. mark it complete) you would modify the task through its Aggregate Root (Company). Since a copy could quickly become outdated, it seems like you would only want a copy to exist while in memory and when saving the Contact, you would only save references to the Tasks.

Coming from a relational database background, how should I model relationships in db4o (or any object database)?

I'm experimenting with db4o as a data store, so to get to grips with it I thought I'd build myself a simple issue tracking web application (in ASP.NET MVC). I've found db4o to be excellent in terms of rapid development, especially for small apps like this, and it also negates the need for an ORM.
However, having come from a SQL Server/MySQL background I'm a little unsure of how I should be structuring my objects when it comes to relationships (or perhaps I just don't properly understand the way object databases work).
Here's my simple example: I have just two model classes, Issue and Person.
public class Issue
{
public string ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public DateTime? SubmittedOn { get; set; }
public DateTime? ResolvedOn { get; set; }
public Person AssignedBy { get; set; }
public Person AssignedTo { get; set; }
}
public class Person
{
public string ID { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
The ID properties are just GUID strings generated by the .NET Guid.NewGuid() helper.
So here's how I initially thought the application would work; please ignore any security concerns etc and assume we already have a few Person objects stored in the database:
User logs in. Query the database for the Person which matches the username and password, and store his/her GUID id as a session variable. Redirect to app home screen.
Logged in user creates a new issue ticket, selecting the user to assign it to from a drop-down list. They fill in the other details (Title, Description etc), and then submit the form.
Query the Person objects in the database (by their GUID ID's) to get an object representing the logged in user and one representing the user the ticket has been assigned to. Create a new Person object (populated with the posted form data), assign the Person objects to the Issue object's AssignedBy and AssignedTo properties, and store it.
This would mean I have two Person objects stored against each Issue record. But what happens if I update the original Person—do all the stored references to that Person in the various issue objects update, or do I have to handle that manually? Are they references, or copies?
Would it be better/more efficient to just store a GUID string for the AssignedBy and AssignedTo fields (as below) and then look up the original person based on that each time?
public class Issue
{
public string ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public DateTime? SubmittedOn { get; set; }
public DateTime? ResolvedOn { get; set; }
public string AssignedByID { get; set; }
public string AssignedToID { get; set; }
}
I think I'm just stuck in a certain way of thinking which is confusing me. If someone could explain it clearly that would be most helpful!
Object-Databases try to provide the same semantics as objects in memory. The rule of thumb is: It works like objects in memory. Object databases store references between the objects in the database. When you update the object, that object is updates. And if you have a reference to that objects, you see the changed version.
In your case, the Issue-objects refer to the person object. When you update that person, all Issues which refer to it 'see' that update.
Of course, primitive types like int, strings, longs etc are handled like value objects and not a reference objects. Also arrays are handled like value objects in db4o, this means a array is stored together with the object and not as a reference. Everything else is stored as a reference, even collections like List or Dictionaries.
Please take a look at:
http://developer.db4o.com/Documentation/Reference/db4o-7.4/java/reference/html/reference/basic_concepts/database_models/object-relational_how_to.html
Best!

Creating a Dynamic Linq filter over List<T>

Ok, I asked this question before, but deleted it as the way I went about describing my problem was wrong.
Firstly, let me state that Im creating a .NET3.5 Winforms app using C# and Plinqo (Professional Linq to Objects) as my ORM. Here's my situation: I have a DataGridview that is populated from a SortableBindingList<T> - in my case, formed from a List<Task> which is simply represented as follows:
public class Task {
public long TaskID { get; set; }
public string TaskDescription { get; set; }
public enumPriority TaskPriority { get; set; }
public DateTime DueDate { get; set; }
public double PercentageComplete { get; set; }
}
Now, I want to provide a Dialog to my user to allow him/her to Filter this list. I envision passing in a list of property names and associated DataType into the Dialog that I can use to populate a ComboBox. So the user will choose which property they want to query from the comboBox and based on the selection the appropriate comparers and UI control will be made available for the user to enter in thier criteria. Lastly, it will contain an AND/OR togglebutton at the end which the user can use to add additional criterion. Each criterion will be an object of type FilterItem as shown below:
public class FilterItem {
public string MappedPropertyName { get; set; }
public enumComparer Comparer { get; set; }
public object FilterValue { get; set; }
public enumOpertor Operator { get; set; }
}
After the user constructs his/her query, I intend to pass this as a List<FilterItem> back to my calling form, which can then iterate thru the list and allow me to filter the original List<Task>.
This is all fine, and something that I can put together with ease. But I want to make sure that the ACTUAL filter mechanism I go with is as strongly-typed as possible, and not using bulit up strings like in the Dynamic Query Library. (I used to do something similar previously with ADO.NET, DataViews and dynamically constructing a RowFilter string)
I've read up on Joseph Albahari's PredicatBuilder and an article on tomasp.net, but I seem heavily confused with it and expression trees in general.
I sincerely seek your assistance in helping me better understand these concepts, and how to go about using it up so that my intended architecture can work with it.
Much appreciation!
Additionally, I know I can do something like:
private SortableBindingList<Task> GetSortedTaskList()
{
List<Task> list = new List<Task>();
var query = DataUtil.GetUserTasks(xSys.Current.UserID);
if (/*description condition met*/)
{
query = query.Where(x => x.TaskDescription.Contains(FilterDesc));
}
if (/*due date condition met*/)
{
query = query.Where(x => x.DueDate >= FilterDate);
}
if (/*priority condition met*/)
{
query = query.Where(x => x.TaskPriority == FilterPriority);
}
...
list = query.ToList();
return new SortableBindingList<ArcTask>(list);
}
but this does not seem very scalable and 'dynamic'.

Resources