MVVM separation of Data Access from ViewModel
I am new to WPF and MVVM and so far I have an app that gets some ContactList objects from the DB2 database and displays their information in the UI. Currently I have a ContactListModel class and an InformationViewModel class which I am binding to. My InformationViewModel class is set as the DataContext for my View. The problem is that my InformationViewModel class also contains my database access code i.e db connection and SQL command and I would like to move this to my ContactListModel class so that I have a separate data access layer. Can anyone help me with this? Thanks!
ContactListModel.cs
public class ContactListModel//: INotifyPropertyChanged
{
public int ContactListID { get; set; }
public string ContactListName { get; set; }
public ObservableCollection<AggregatedLabelModel> AggLabels { get; set; }
}
InformationViewModel.cs
public class InformationViewModel
{
public InformationViewModel()
{
GetData();
}
private ObservableCollection<ContactListModel> myContactLists;
public IEnumerable<ContactListModel> ContactLists
{
get { return myContactLists; }
}
public void GetData()
{
myContactLists = new ObservableCollection<ContactListModel>();
DB2Connection conn = null;
try
{
conn = new DB2Connection("SERVER CONNECTION;");
}
catch (Exception ex)
{
System.Windows.MessageBox.Show(ex.Message + " " + ex.InnerException);
}
//get all contactLists and their labels
DB2Command command = new DB2Command("SELECT QUERY");
command.Connection = conn;
conn.Open();
//Add uniqu开发者_StackOverflowe contactLists to dictionary
Dictionary<int, ContactListModel> myContactDictionary = new Dictionary<int, ContactListModel>();
using (DB2DataReader dr = command.ExecuteReader())
{
while (dr.Read())
{
int id = Convert.ToInt32(dr["CONTACT_LIST_ID"]);
if (!myContactDictionary.ContainsKey(id))
{
ContactListModel contactList = new ContactListModel();
contactList.ContactListID = id;
contactList.ContactListName = dr["CONTACT_LIST_NAME"].ToString();
contactList.AggLabels = new ObservableCollection<AggregatedLabelModel>()
{
new AggregatedLabelModel()
{
ID = Convert.ToInt32(dr["LABEL_ID"]),
Name = dr["LABEL_NAME"].ToString()
}
};
myContactDictionary.Add(id, contactList);
}
else
{
//populate existing contact lists with remaining labels
ContactListModel contactList = myContactDictionary[id];
contactList.AggLabels.Add
(
new AggregatedLabelModel()
{
ID = Convert.ToInt32(dr["LABEL_ID"]),
Name = dr["LABEL_NAME"].ToString()
}
);
}
}
}
conn.Close();
}
You'll need to read about Repository design pattern:
http://martinfowler.com/eaaCatalog/repository.html
http://msdn.microsoft.com/en-us/library/ff649690.aspx
That's creating a kind of in-memory-like object collection which translates your domain objects (aka "business objects", "business entities") to some format that may understand an underlying storage.
Repository will be providing the access to domain objects, meaning that your managers, models and others will understand the access to some repository as an actual collection, and that's a total abstraction letting you to separate data access logic from the business.
Your model will have methods that are going to fill, store or look for DTO translated into domain objects and later, using your repositories, to data.
A rough mock up, you can add SaveContact and DeleteContact methods to the DataLayer class.
public class DataLayer
{
public ObservableCollection<ContactModel> GetContacts()
{
var tList = new ObservableCollection<ContactModel>();
//load from db into tList
return tList;
}
}
public class ContactModel
{
public int ContactListID { get; set; }
public string ContactListName { get; set; }
public ObservableCollection<AggregatedLabelModel> AggLabels { get; set; }
}
public class ContactsViewModel
{
public ObservableCollection<ContactModel> ListOfContacts;
public ContactsViewModel()
{
var dl = new DataLayer();
ListOfContacts = dl.GetContacts();
}
}
精彩评论