Handling Data Access Layer Exception in MVVM using Inversion on Control - c#

I'm studding MVVM in C#.
I want to use Inversion of Control (IoC). I use the framework Unity.
I don't understand how to handling exception that could be raised from Data Access Layer.
Here a little easy example I do for study:
-- i have omitted the manage of Model validation (IDataErrorInfo) and Services for ViewModel (ex: DialogService) --
XAML View
<TextBox ... Text="{Binding Path=Id}" />
<TextBox ... Text="{Binding Path=Name}"/>
DESIGN APPLICATION
MODEL
{
public class User : INotifyPropertyChanged
{
private int _id;
public int Id
{
get{return _id;}
set
{
_id = value;
this.OnPropertyChanged("Id");
}
}
private string _name;
public string Name
{
get{return _name;}
set
{
_name = value;
this.OnPropertyChanged("Name");
}
}
public User(int i, string n)
{
_id = i;
_name = n;
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}
}
DATA ACCESS LAYER
Interface
public interface IDataAccessLayer
{
Model.User GetUser();
}
Concrete class
public class ConcreteDataAccessLayer : IDataAccessLayer
{
public ConcreteDataAccessLayer(){}
Model.User IDataAccessLayer.GetUser()
{
//could throw Exception connecting with data source
}
}
BUSINESS LAYER
public class BusinessLayer
{
public BusinessLayer(IDataAccessLayer dataAccessLayer)
{
if (dataAccessLayer == null)
{
throw new ArgumentNullException("dataAccessLayer");
}
this._dataAccessLayer = dataAccessLayer;
}
private IDataAccessLayer _dataAccessLayer;
private QuestionStak.Model.User _user;
internal QuestionStak.Model.User User
{
get
{
if (_user == null)
_user = _dataAccessLayer.GetUser();
return _user;
}
}
}
VIEWMODEL
public class ViewModel : INotifyPropertyChanged
{
public ViewModel(BusinessLayer bl)
{
if (bl == null)
{
throw new ArgumentNullException("BusinessLayer");
}
_businessLayer = bl;
}
private BusinessLayer _businessLayer;
public int Id
{
get
{
return _businessLayer.User.Id;
}
set
{
_businessLayer.User.Id = value;
}
}
public string Name
{
get
{
return _businessLayer.User.Name;
}
set
{
_businessLayer.User.Name = value;
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
APPLICATION
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
//Inversion of control
IUnityContainer container = new UnityContainer();
//Created as singleton
container.RegisterType<IDataAccessLayer, ConcreteDataAccessLayer>(new ContainerControlledLifetimeManager());
container.RegisterType<BusinessLayer, BusinessLayer>(new ContainerControlledLifetimeManager());
MainWindow win = container.Resolve<MainWindow>();
win.DataContext = container.Resolve<ViewModel>();
win.Show();
}
}
Principles follow
simple constructors (Unity catch all exception and follow http://blog.ploeh.dk/2011/03/03/InjectionConstructorsshouldbesimple/)
ViewModel must hide Model structure
So I have a problem that I don't understands how to solve:
If ConcreteDataAccessLayer can't load data (Ex: server not available) during loading of ViewModel the statement _dataAccessLayer.GetUser() throw the exception and in could not manage it (catch by Unity conteiner)
If somewhere during the loading I manage the exception, the data binding cause the throw of a null exception because _businessLayer.User is null (unable to load the view)
Please, have someone a clean solution for this problem?
Thanks!

If ConcreteDataAccessLayer can't load data (Ex: server not available) during loading of ViewModel the statement _dataAccessLayer.GetUser() throw the exception and in could not manage it (catch by Unity conteiner)
I'm not sure what you mean by 'in could not manage it (catch by Unity container)', as I would only expect a wrapped Unity exception if there was a problem constructing the types that Unity is resolving. Either way, you would still be able to handle the exception yourself. You would probably want to do this in your presentation layer, so that you could bring up a dialog etc.
If somewhere during the loading I manage the exception, the data binding cause the throw of a null exception because _businessLayer.User is null (unable to load the view)
Yes, if you've handled the error in your business layer, then you would need to guard against the User property being null.
However, I think your approach should be reconsidered. Your IDataAccessLayer and BusinessLayer types seem like big dependencies which is going to minimise the amount of code reuse, as well as making unit testing more difficult.
You should try and minimise the dependencies. If your view model is only interested in users for example, then you could use the repository pattern (well really a data access object pattern) to inject a user repository.
Alternatively if you wish to use rich business objects, then your view models would take your user business object as the dependency. You may then decide to expose the model directly to the view, depending on if you wish to violate the DRY principle (which you are currently doing), or the Law of Demeter.
I would also consider using an MVVM framework if you're using the MVVM design pattern.

Related

Implement data access layer best practices in .net Project MVC

I would like to improve my .NET project by adding another layer when accessing the database. This is my code:
namespace Company.Models
{
public static class AgencyBean
{
[WebMethod]
[ScriptMethod(UseHttpGet = true)]
public static String createGUID(string name)
{
DataAccess dataAccess = new DataAccess();
bool exists = dataAccess.checkIfExists(Id);
if(exist)
{
dataAccess.delete(Id);
}
retur "ok";
}
}
}
I placed DataAccess class in a separate folder called "Helpers" and it contains most of my queries:
public class DataAccess
{
public bool checkIfExists(String Id)
{
try
{
SqlConnection cnn = new SqlConnection(dataConnection);
cnn.Open();
SqlCommand check_Id = new SqlCommand("SELECT COUNT(*) FROM TABLE_GUID WHERE ([USER_ID] = #Id)", cnn);
check_Id.Parameters.AddWithValue("#Id", Id);
int UserExist = (int)check_Id.ExecuteScalar();
if (UserExist > 0)
{
return true;
}
else
{
return false;
}
}
catch (SqlException ex)
{
Debug.WriteLine("SQL Exception " + ex);
DisplaySqlErrors(ex);
throw ex;
}
}
}
public class AgentBeanController : Controller
{
// GET: AgentBean
public ActionResult Index(string name)
{
return View();
}
[AllowAnonymous]
[WebMethod]
public string AgentURL() //here we create Agent URL and return it to the view
{
string var = Models.AgentBean.createGUID("TODO");
return var;
}
}
I'm accessing the database pretty much in very direct way. How would it be with a better technique, so this access can be more secure, like accessing thru a service layer?
I'm connecting to a existing sql database in some server and working with MVC architecture in my project.
So here is what I have done in the past.
First, that is your "models" namespace... models should never have database connectivity. Instead you have a seperate class, such as a controller, that hydrates some model.
Second, I've had a "service" class, which hooks up to a "repository" class. The repository class implements an interface to identify the exact "type" of database you're using.. but if that's not a part of your requirements you probably don't need to go that far.
Third, look up dependency injection (aka, DI). There are several frameworks out there. Personally I've used Autofac, but others exist as well to get the job done easier.
Fourth, on your your "controllers", "services" and "respository" classes, implement dependency injection, as well as any interfaces as needed to form a contract.
Fifth, I would use an actual controller namespace and not be working out of your models namespace to be pushing http calls band and forth.... Instead, create an action in your controller class, and instantiate an instance of your "agencyBean", hydrate it with data, and return that model out to your view.
Basically, in a scenario like this you're trying to keep each component doing what it is designated to do... breaking down responsibilities into smaller pieces and focusing on that. Your controller should just "fetch" your model and maybe do some transformations on it as needed or any other business-type logic.
Your service should handle the communication between your controller and your database layer.
Your data access layer (ie, in this case, some "repository" class...) would do all of those new data connections and/or setting up calls to stored procedures or queries.
Doing things this way has a lot of benefit. Some of the big ones are maintainability, readability, code re-use. Sure it makes your project a bit more complicated in terms of files sitting wherever... but that can be a good thing. It's so much better than slamming everything into one single class and have it do everything :)
But, just FYI, this is from an implementation I've done in the past... I'm sure there are better ways but this setup worked quite well for my team and I.
Here is a small example using some of your code you posted. I DID NOT check this for typos and it wouldn't compile, but should help give a general idea of what I'm talking about....
namespace Company.Models
{
public class AgencyBean
{
public AgencyName{get;set;}
public AgencyId{get;set;}
// other properties...
}
}
namespace Company.Controllers
{
public class MyController : Controller
{
private readonly IMyService myService;
public MyController(IMyService myService) // <-- this is your dependency injection here...
{
this.myService = myService;
}
[WebMethod]
[ScriptMethod(UseHttpGet = true)]
public static String createGUID(string name)
{
var model = new AgencyBean();
model.AgencyId = 1;
model = myService.getAgency(agencyBean);
return model;
}
}
}
namespace Company.Services
{
public class MyService
{
private readonly IMyRepository myRepository;
public MyService(IMyRepository myRepository) // <-- this is your dependency injection here...
{
this.myRepository = myRepository;
}
public AgencyBean getAgency(AgencyBean model){
var dataTable = myRepository.getAgencyData(model.AgencyId);
// fill other properties of your model you have...
// ...
// ...
return model;
}
}
}
namespace Company.Repositories
{
public class MyRepository : IDatabaseCommon // <-- some interface you would use to ensure that all repo type objects get connection strings or run other necessary database-like setup methods...
{
private readonly String connectionString{get;set;}
public MyRepository()
{
this.connectionString = //get your connection string from web.config or somewhere else...;
}
public DataTable getAgencyData(int id){
var dataTable = new DataTable();
// perform data access and fill up a data table
return dataTable;
}
}
}

C# MVVM Handling and Passing UserID to different Models and ViewModels

My current implementation of passing UserID in my application is through the constructor.
i.e. SomeObject s = new SomeObject(userID)
Where in there is a code behind that does things based on the userID. The userID is further keep tracked by adding another property named "CurrentUser", however this seems to be a dirty solution as I have to implement it to all ViewModels and it seems to violate the "DRY" concept.
The second approach I have in mind is creating a public static variable on my MainWindowViewModel where all my other models can refer to it as MainWindowViewModel.CurrentUser.
Is one of the two approach the correct way to do this or is there a better approach that i don't know about?
You need to carefully analyze up front what you want to achieve with your application. Are you happy with there only ever being one selected client? Or will you need to have multiple clients being viewed or edited at a time (i.e. you have an MDI style app)?
Going with the single client approach is easy, you can implement the global property bag as already mentioned in other answers. But I will advise caution: if you build your app on the assumption there will only ever be one selected client it becomes a real PITA to try to refactor to make it multi-client capable. Using a centralized property bag or "session service" like this is indeed decoupling state from the VM, but the centralized service can still turn into a monstrosity over time and you build up too much dependence on it.
If you do want to go the multi-client route, then you are on the right track - but instead of passing a client identifier in on the constructor, pass (inject) the entire client data object. The chances are that you already have most of the client details available from the piece of UI that invokes the client oriented VM, so pass it in and save having to make another trip to your database to get the details.
Don't tie a current user to a ViewModel. I typically opt for a SessionService of some kind. If you're using Dependency Injection (DI), register a singleton of an ISessionService and concrete implementation. If your not using DI, then just have your app start create a singleton, like a SessionService.Current. Then you can put any items you need in here. Then each ViewModel can ask for the SessionService.Current.User and they have it. Your ViewModels shouldn't know about each other, but they can know about services. This keeps it DRY and loosely coupled, especially if you only access these session variables using the interface of an ISessionService and not the concrete implementation. This allows you to mock one up very easily without changing any ViewModel code.
What you have here is the problem of Communication between ViewModels. There are a number of solutions but my fave is the Mediator Pattern:
using System;
namespace UnitTestProject2
{
public class GetDataViewModel
{
IMediator mediator;
public GetDataViewModel(IMediator mediator)
{
this.mediator = mediator;
this.mediator.ListenFor("LoggedIn", LoggedIn);
}
protected string UserId;
protected void LoggedIn(Object sender, EventArgs e)
{
UserId = sender.ToString();
}
}
public class LoginViewModel
{
IMediator mediator;
public LoginViewModel(IMediator mediator)
{
this.mediator = mediator;
}
public string UserId { get; set; }
public void Login(string userid)
{
this.UserId = userid;
this.mediator.RaiseEvent("LoggedIn", this.UserId);
}
}
public interface IMediator
{
public void ListenFor(string eventName, EventHandler action );
public void RaiseEvent(string eventName, object data);
}
}
I Haven't implemented the Mediator here, because it can get quite involved and there are a number of packages available. but you can see the idea from my simple interface. Essentially the Mediator provides a Global list of EventHandlers which any Viewmodel can call or add to. You still have the problem of where to store the event names. Its nice to have these in enums, but that gives you a coupling problem. (a problem I usually ignore)
Alternatively you can have a Controller or (MasterViewModel if you love MVVM)
using System;
namespace UnitTestProject3
{
public class GetDataViewModel
{
protected string UserId;
public void LoggedIn(Object sender, EventArgs e)
{
UserId = sender.ToString();
}
}
public class LoginViewModel
{
public EventHandler OnLogin;
public string UserId { get; set; }
public void Login(string userid)
{
this.UserId = userid;
if (this.OnLogin != null)
{
this.OnLogin(this.UserId, null);
}
}
}
public class Controller // or MasterViewModel
{
public void SetUp()
{
GetDataViewModel vm1 = new GetDataViewModel();
LoginViewModel vm2 = new LoginViewModel();
vm2.OnLogin += vm1.LoggedIn;
//wire up to views and display
}
}
}

Update UI after receiving data on a TCP Socket

I don't think I am even asking this right but here it goes.
I have a .NET CF app that displays a datagrid of info. This app is connected by TCP Sockets to a Central Server that will periodically broadcast out data.
How do I get my datagrid on my ShellForm to update. Feels wrong to have a reference to my ShellForm in my DAL where the Socket stuff is happening.
Would I use a Delegate or Async Callback? Just looking for a little guidance. Thanks!
The DAL can just publish an Event, and then the GUI can subscribe to it.
The reference (and dependency) will be from the GUI to the DAL.
Watch your thread-safety as well.
I'd suggest that your UI shouldn't know anything about your DAL at all. What I'd do for this would be to create an intermediate "presenter" class that watches the DAL and then can notify the UI, either via an event, callback or whatever.
I would most likely create a presenter class that implements INotifyPropertyChanged, which would allow you to directly watch the event or to data bind to the property that you're using to fill your grid. The presenter would also handle marshaling to the UI context, so neither the UI or the DAL would have to worry about it.
Some sort-of pseudo code might look like this. Bear in mind I have all sorts of infrastructure bits in my code, so this is not likely to just compile, but it should give you a flavor of how I'd attack the problem.
class PointPresenter : INotifyPropertyChanged
{
private IDataService DAL { get; set; }
protected Control EventInvoker { get; private set; }
public PointPresenter()
{
// get your DAL reference however you'd like
DAL = RootWorkItem.Services.Get<IDataService>();
EventInvoker = new Control();
// this is required to force the EE to actually create the
// control's Window handle
var h = EventInvoker.Handle;
}
protected void RaisePropertyChanged(string propertyName)
{
try
{
if (m_disposed) return;
EventInvoker.BeginInvokeIfRequired(t =>
{
try
{
PropertyChanged.Fire(this, propertyName);
}
catch (Exception e)
{
Debug.WriteLine(e);
}
});
}
catch (ObjectDisposedException)
{
// if the Form to which we're sending a message is disposed,
// this gets thrown but can safely be ignored
}
catch (Exception ex)
{
// TODO: log this
}
}
public int MyDataValue
{
get { return DAL.Data; }
set
{
if (value == MyDataValue) return;
DAL.Data = value;
RaisePropertyChanged("MyDataValue");
}
}
}

WPF MVVM Light unit testing ViewModels

I am not a regular with the MVVM pattern and this is basically my first time playing with it.
What I used to do ("normal" WPF), was creating my Views with a Business layer and perhaps a datalayer (which usually contains my entities created by a service or the Entity Framework).
Now after some toying I created a standard template from MVVM Light and did this:
Locator:
public class ViewModelLocator
{
static ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic)
{
SimpleIoc.Default.Register<IUserService, DesignUserService>();
}
else
{
SimpleIoc.Default.Register<IUserService, IUserService>();
}
SimpleIoc.Default.Register<LoginViewModel>();
}
public LoginViewModel Login
{
get
{
return ServiceLocator.Current.GetInstance<LoginViewModel>();
}
}
}
Login ViewModel:
public class LoginViewModel : ViewModelBase
{
private readonly IUserService _userService;
public RelayCommand<Object> LoginCommand
{
get
{
return new RelayCommand<Object>(Login);
}
}
private string _userName;
public String UserName
{
get { return _userName; }
set
{
if (value == _userName)
return;
_userName = value;
RaisePropertyChanged("UserName");
}
}
/// <summary>
/// Initializes a new instance of the LoginViewModel class.
/// </summary>
public LoginViewModel(IUserService userService)
{
_userService = userService;
_closing = true;
}
private void Login(Object passwordBoxObject)
{
PasswordBox passwordBox = passwordBoxObject as PasswordBox;
if (passwordBox == null)
throw new Exception("PasswordBox is null");
_userService.Login(UserName, passwordBox.SecurePassword, result =>
{
if (!result)
{
MessageBox.Show("Wrong username or password");
}
});
}
}
Binding and commands work fine so there is no questions. Business mockup class for design and test time:
public class DesignUserService : IUserService
{
private readonly User _testUser;
private readonly IList<User> _users;
public void Login(String userName, SecureString password, Action<Boolean> callback)
{
var user = _users.FirstOrDefault(u => u.UserName.ToLower() == userName.ToLower());
if (user == null)
{
callback(false);
return;
}
String rawPassword = Security.ComputeHashString(password, user.Salt);
if (rawPassword != user.Password)
{
callback(false);
return;
}
callback(true);
}
public DesignUserService()
{
_testUser = new User
{
UserName = "testuser",
Password = "123123",
Salt = "123123"
};
_users = new List<User>
{
_testUser
};
}
}
UserData is a static class which makes calls to the database (Entity Framework).
Now I have my test:
[TestClass]
public class Login
{
[TestMethod]
public void IncorrectUsernameCorrectPassword()
{
IUserService userService = new DesignUserService();
PasswordBox passwordBox = new PasswordBox
{
Password = "password"
};
userService.Login("nonexistingusername", passwordBox.SecurePassword, b => Assert.AreEqual(b, false));
}
}
Now my test is not on the ViewModel itself but directly to the Business layer.
Basically I have 2 questions:
Am I on the right path, or is there a fundamental flaw in my pattern implementation?
How can I test my ViewModel?
Your view model has one relevant piece of code worth testing, which is Login method. Given that it's private, it should be tested it via LoginCommand.
Now, one might ask, what is the purpose of testing command when you already have test for underlying business logic? The purpose is to verify that business logic is called and with correct parameters.
How do one goes with such test? By using mock. Example with FakeItEasy:
var userServiceFake = A.Fake<IUserService>();
var testedViewModel = new LoginViewModel(userServiceFake);
// prepare data for test
var passwordBox = new PasswordBox { Password = "password" };
testedViewModel.UserName = "TestUser";
// execute test
testedViewModel.LoginCommand.Execute(passwordBox);
// verify
A.CallTo(() => userServiceFake.Login(
"TestUser",
passwordBox.SecurePassword,
A<Action<bool>>.Ignored)
).MustHaveHappened();
This way you verify that command calls business layer as expected. Note that Action<bool> is ignored when matching parameters - it's difficult to match Action<T> and Func<T> and usually not worth it.
Few notes:
You might want to reconsider having message box code in view model (this should belong to view, view model should either request or notify view to display popup). Doing so, will also make more through testing of view model possible (eg. not needing to ignore that Action argument)
Some people do test INotifyPropertyChanged properties (UserName in your case) - that event is raised when property value changes. Since this is lot of boilerplate code, using tool /library to automate this process is highly suggested.
You do want to have two sets of tests, one for view model (as in the example above) and one for underlying business logic (your original test). In MVVM, VM is that extra layer which might seem to be of little use - but that's the whole point - to have no business logic there and rather focus data rearrangement/preparation for views layer.

Linq: scoped DataContext, unit-of-work, repository

I have been researching about the unit-of-work and the repository pattern in C#. AFAIK, DataContext implements the unit of work pattern, and can be used to implement a repository interface. One last piece that's lacking in DataContext is a way to share this resource globally within a predefined scope.
I briefly looked at NCommon as a solution to this missing piece. Would you share your experience in NCommon, or recommend other solutions? Please also correct me if I have misunderstood. Thanks.
I always worked with DataContext in the same way NHibernate does: Having a static way to get it and different storages for storing it. For instance, it could be stored in the HttpContext.Current.Items collection for a web based application, or in Call.Context for the unit tests. When do you create the instance and when do you close it will depend on the scenario. Again, for web it make sense to do it on the Request_begin and Request_end events of your application. For unit tests, maybe on the setup and teardown.
Hope it helps.
Edit: Here's some implementation
public abstract class DataContextProvider
{
public abstract DataContext GetCurrent();
public abstract void OpenNew();
public void CloseCurrent()
{
var current = GetCurrent();
current.Dispose();
}
}
In your data context you add this:
public static DataContextProvider Provider { private get; set; }
public static DataContext Current { get { return Provider.GetCurrent(); } }
For web:
In your web project you put this class:
public class WebDataContextProvider : DataContextProvider
{
private const string Key = "WebDataContextProvider.DataContext";
public override DataContext GetCurrent()
{
return (DataContext)HttpContext.Current.Items[Key];
}
public override void OpenNew()
{
HttpContext.Current.Items[Key] = new DataContext();
}
}
And in your global.asax:
You add a field of type WebDataContextProvider:
WebDataContextProvider dataContextProvider = new WebDataContextProvider();
You override the application start event for doing:
DataContext.Provider = dataContextProvider;
In your Request Begin event you put:
dataContextProvider.OpenNew();
And in your Request End event you put:
dataContextProvider.CloseCurrent();
For test
For your test projects you can follow the same logic, but creating a TestDataContextProvider, like:
public class WebDataContextProvider : DataContextProvider
{
[ThreadStatic]
private static DataContext Current;
public override DataContext GetCurrent()
{
return Current;
}
public override void OpenNew()
{
Current = new DataContext();
}
}
And in your open and close the data context in your SetUp and TearDown methods, and configuring the "current provider" in the constructor of the Test or the TestFixtureSetUp
Hope it helps.

Categories