Runtime error when creating a constructor for my viewModel - c#

I have designed a simple UI that displays connection strings read from a web.config file. I have followed the MVVM light framework fairly close and when I instantiate my ConnectionStringViewModel, I get the error. If I take it out, things work but then I can't reach the data I need to display. Here is some code:
Connection String ViewModel:
public string SqlConnectionString
{
get { return _sqlConnString; }
set
{
if (_sqlConnString == value)
return;
_sqlConnString = value;
RaisePropertyChanged(SqlConnString);
}
}
public ConnectionStringViewModel(*IValidationService validationService*)
{
_validationService = validationService;
_validationService.SqlConnectionStringService(
(item, error) =>
{
if (error != null)
{
// Report error here
return;
}
SqlConnectionString = item.ConnString;
});
}
ValidationService:
public class ValidationService : IValidationService
{
private readonly Configuration _webConfig = WebConfigurationManager.OpenWebConfiguration(#"C:\Source\web.config");
public void SqlConnectionStringService(Action<ConnectionString, Exception> callback)
{
var connString = new ConnectionString(_webConfig.ConnectionStrings.ConnectionStrings["SomeConnectionString"].ConnectionString);
callback(connString, null);
}
}
IValidationService:
public interface IValidationService
{
void SqlConnectionStringService(Action<ConnectionString, Exception> callback);
}

With DI you want to avoid executing methods in your constructors. This is because it's possible the DI bootstrapper hasn't finished mapping yet and could cause NullReference exceptions.
You don't say what the exception is so hard to say.

Related

Using the Decorator Pattern to Conditionally Replace Behaviour Instead of Extending

Initially I had this structure:
interface IFileBackup
{
void Backup();
}
class BackUpMechanism1 : IFileBackup
{
void Backup()
{
//Back it up
}
}
class BackUpMechanism2 : IFileBackup
{
void Backup()
{
//Back it up in another way
}
}
class Client
{
//Instantiation of both mechanisms
//
try
{
backUpMechanism1.Backup();
}
catch(Exception ex)
{
backupMechanism2.Backup();
}
}
I was told that this was not a very clean design and to redesign it using the decorator pattern. The client should not know about the two back up mechanisms but just call backup and then the first mechanism should try to back up the file and if that fails then use mechanism 2. However I don't understand how to use the decorator pattern because from my understanding it extends functionality but doesn't replace functionality - which is what I want... How do I archive that? I have tried the following:
interface IFileBackup
{
void Backup();
}
class BackupMechanism1 : IFileBackup
{
public void Backup()
{
try
{
Console.WriteLine("Trying to back up to the cloud...");
throw new Exception();
}
catch(Exception ex)
{
Console.WriteLine("Oops that failed. We need to back up locally instead...");
}
}
}
class BackupMechanism2 : IFileBackup
{
IFileBackup _fileBackup;
public BackupMechanism2(IFileBackup fileBackup)
{
_filebackup = fileBackup;
}
public void Backup()
{
//All examples I have seen does this. But doesn't make sense in my case?
_fileBackup.Backup();
Console.WriteLine("Backing up locally");
}
}
//The client does not care about how the backup is done
class Client
{
static void Main()
{
//This is not right, but not sure what I should do in the client.
BackupMechanism2 localBackup = new BackupMechanism2(new BackupMechanism1());
localBackup.Backup();
Console.Read();
}
}
So essentially what I want to achieve is to have two backup mechanisms. Have the client just say backup I don't care how. Let the first mechanism try it's backup method if that fails then try the second method. I'm trying to use the decorator pattern to extend(replace) the backup behaviour of the first mechanism if it fails. I'm struggling to come up with a design that makes sense.
A very clean approach of implementing this would be adding a composite IFileBackup taking an array of IFileBackup objects, and trying them one by one until a working solution is found:
class CompositeBackup {
private readonly IFileBackup[] chain;
public CompositeBackup(params IFileBackup[] chain) {
this.chain = chain.ToArray();
}
public void Backup() {
foreach (var backup in chain) {
try {
backup.Backup();
return;
} catch {
continue;
}
}
throw new InvalidOperationException();
}
}
Now the client simply does this:
IFileBackup backup = new CompositeBackup(
new BackupMechanism1()
, new BackupMechanism2()
);
backup.Backup();
If you later decide to add BackupMechanism3 and BackupMechanism4, the user would need to add another object to the chain of backups. The rest of the code would remain unchanged. In addition, backup mechanisms themselves would remain unaware of other mechanisms' existence, which also simplifies the code.
The decorator pattern, in this case, can be used to provide fallback implementations. You can find plenty of obvious examples in the .Net streams implementation.
So with that in mind, your code should look something like this:
class abstract BaseFileBackup
{
internal BaseFileBackup Fallback;
internal BaseFileBackup(BaseFileBackup fallback) { Fallback = fallback; }
internal BaseFileBackup() { }
internal abstract void DoBackupWork();
internal void Backup()
{
try { DoBackupWork(); }
catch { if(Fallback != null) Fallback.Backup(); else throw; }
}
}
class BackUpMechanism1 : BaseFileBackup
{
internal BackUpMechanism1 (BaseFileBackup fallback): base(fallback) {}
internal BackUpMechanism1 (): base() {}
internal void DoBackupWork()
{
//Back it up
}
}
class BackUpMechanism2 : BaseFileBackup
{
internal BackUpMechanism2 (BaseFileBackup fallback): base(fallback) {}
internal BackUpMechanism2 (): base() {}
internal void DoBackupWork()
{
//Back it up in another way
}
}
// and to call it
class Client
{
static void Main()=>
new BackupMechanism2(new BackupMechanism1()).Backup();
}
Decorator Pattern is the WRONG choice in this scenario.
The problem that you are dealing with here is
under condition x call one method
under condition y call a different method
...
This is the precondition for the Strategy Pattern, and your initial solution was quite close to that. The problem in my mind is that you are using an Exception to determine the program flow, which is a BAD thing to do: exceptions cost stack space, and they should only be thrown under EXCEPTIONAL circumstances. Whereas in your case, it is expected that a given strategy will not work
IFileBackupStrategy
{
bool Backup(File fileToBackup);
}
IFileBackupContext
{
File ForBackup { set; }
bool Backup();
}
class CloudBackUp : IFileBackupStrategy
{
private bool _success;
public bool Backup(File fileToBackup)
{
// code to do backup omitted
// it will set the value of _success to false if it was unsuccessful
return _success;
}
}
class LocalBackUp : IFileBackupStrategy
{
private bool _success;
public bool Backup(File fileToBackup)
{
// code to do backup omitted
// it will set the value of _success to false if it was unsuccessful
return _success;
}
}
public class FileBackupContext : IFileBackupContext
{
private IEnumerable<IFileBackupStrategy> _backupStrategies
public Context(IEnumerable<IFileBackupStrategy> backupStrategies)
=> _backupStrategies = backupStrategies;
public File ForBackup { set; private get; }
public bool Backup()
{
bool successFlag;
foreach(var strategy in _backupStrategies)
{
successFlag = strategy.Backup(ForBackup);
if(successFlag) break;
}
return successFlag;
}
}
In this case, all that the client needs to be aware of is the IFileBackupContext, and not the strategy employed to do the saving.
public class MyBackupClient
{
private IFileBackupContext _context;
public MyBackupClient(IFileBackupContext context) => _context = context;
void SomeMethodThatInvokesBackingUp()
{
_context.ForBackup = new File(/* */);
if(!_context.Backup())
{
Console.WriteLine("Failed to backup the file");
}
}
}
The beauty of this design is that you can add more IFileBackupStrategy implementations, register them with your DI Container and voila they are instantly available to the client without a single code change or the need for re-compilation (though that will ultimately depend upon how you are populating your DI Container)
The decorator pattern is a method of adhering to the O principle in SOLID: which is
Open for extension and closed for modification
This means that you would use the decorator pattern to decorate an existing class, one that should not be changed and yet does not exhibit the behaviour required. The clue is in the name of the pattern: Decorator adds something, it does not change anything.
The Decorator Pattern is a Structural Pattern, whereas the Strategy Pattern, and what you are looking for, is a Behavioural Pattern
This example can be extended of course to report back the strategy which was ultimately employed, and also (if required) any reasoning for why alternate strategies were not.
Edited: in response to Blindy's comment below. Here is the paradigm for the decorator pattern, which should demonstrate how it is not the correct pattern for this problem:
class Image
{
void Render() { /* */ }
}
class FramedImage : Image
{
private Image _originalImage;
public FramedImage(Image original) => _originalImage = original;
new public void Render()
{
/* code to render a frame */
_originalImage.Render();
}
}
Image originalImage = new Image();
Image framedImage = new FramedImage(originalImage);
Image toRender = originalImage;
toRender.Render() // Renders the original image
toRender = framedImage;
toRender.Render(); // Renders the original image in a frame
It should be observed that there is no need to assign each Image to the toRender variable, that is done solely to demonstrate that a decorator is a decorated.
As you can see from this example, the decorator pattern adds behaviour, and it also invokes the decorated item's behaviour.
Edited: Further to the question posed by DSF below. Here is the full listing for a console app demonstrating how to achieve this using Unity 5.8.6
The code takes advantage of the new Tuple from C# 7.0.
I've just used some random number generation to determine whether or not each strategy implementation succeeds in performing its task.
using System;
using System.Collections.Generic;
using System.IO;
using Unity;
using Unity.Injection;
namespace StrategyPattern
{
public interface IFileBackupContext
{
FileStream ForBackup { set; }
(bool success, string strategy) Backup();
}
public interface IFileBackupStrategy
{
(bool success, string name) Backup(FileStream fileToBackup);
}
internal class LocalBackUp : IFileBackupStrategy
{
private bool _success = false;
public (bool success, string name) Backup(FileStream fileToBackup)
{
// code to do backup omitted
var random = new Random(DateTime.Now.Millisecond);
_success = (random.Next() % 3) == 0;
if(_success) fileToBackup.Close();
// it will set the value of _success to false if it was unsuccessful
return (_success, "LocalBackUp");
}
}
internal class CloudBackUp : IFileBackupStrategy
{
private bool _success = false;
public (bool success, string name) Backup(FileStream fileToBackup)
{
// code to do backup omitted
var random = new Random(DateTime.Now.Millisecond);
_success = (random.Next() % 3) == 0;
if (_success) fileToBackup.Close();
// it will set the value of _success to false if it was unsuccessful
fileToBackup.Close();
return (_success, "CloudBackUp");
}
}
public class FileBackupContext : IFileBackupContext
{
private readonly IEnumerable<IFileBackupStrategy> _backupStrategies;
public FileBackupContext(IEnumerable<IFileBackupStrategy> backupStrategies)
=> _backupStrategies = backupStrategies;
public FileStream ForBackup { set; private get; }
public (bool success, string strategy) Backup()
{
foreach (var strategy in _backupStrategies)
{
var (success, name) = strategy.Backup(ForBackup);
if (success) return (true, name);
}
return (false, "");
}
}
public class MyBackupClient
{
private IFileBackupContext _context;
public MyBackupClient(IFileBackupContext context) => _context = context;
public void BackgUpMyFile()
{
_context.ForBackup = new FileStream("d:\\myfile", FileMode.OpenOrCreate);
(bool success, string strategy) = _context.Backup();
if (!success)
{
Console.WriteLine("Failed to backup the file");
return;
}
Console.WriteLine($"File backed up using [{strategy}] strategy");
}
}
public class Bootstrap
{
private readonly IUnityContainer _container;
public Bootstrap()
{
_container = new UnityContainer();
_container.RegisterType<IFileBackupContext, FileBackupContext>();
_container.RegisterType<IFileBackupStrategy, LocalBackUp>("local");
_container.RegisterType<IFileBackupStrategy, CloudBackUp>("cloud");
_container.RegisterType<MyBackupClient>();
_container.RegisterType<Func<IEnumerable<IFileBackupStrategy>>>(new InjectionFactory(c =>
new Func<IEnumerable<IFileBackupStrategy>>(() =>
new[]
{
c.Resolve<IFileBackupStrategy>("local"),
c.Resolve<IFileBackupStrategy>("cloud")
}
)));
}
public MyBackupClient GetClient() => _container.Resolve<MyBackupClient>();
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Press ESC to quit ...");
Console.WriteLine("Press any other key to try again.");
Console.WriteLine();
var client = new Bootstrap().GetClient();
do
{
client.BackgUpMyFile();
} while (Console.ReadKey().Key != ConsoleKey.Escape);
}
}
}

Ninject equivalent to Autofac IIndex

Is there a Ninject equivalent to Autofac IIndex. In other words I need to get a collections of all registered items that have the name of registration.
In Autofac you would do it like so
EDIT: made a change to make things more clear.
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<Add>().Keyed<ICommand>("add");
builder.RegisterType<Add>().Keyed<ICommand>("sub");
builder.RegisterType<Calculator>().As<Calculator>();
var container = builder.Build();
var calc = container.Resolve<Calculator>();
calc.Run();
}
public class Calculator
{
IIndex<string, ICommand> commands;
public Calculator(IIndex<string, ICommand> commands)
{
this.commands = commands;
}
public void Run()
{
var result = true;
do
{
var cmd = Console.ReadLine().Split(' ');
ICommand command;
if (commands.TryGetValue(cmd[0], out command))
{
result = command.Do(cmd.Skip(1).ToArray());
}
else
{
Console.WriteLine("Command not found");
}
} while (!result);
}
}
public interface ICommand
{
bool Do(string[] data);
}
public class Add : ICommand
{
public bool Do(string[] data)
{
Console.WriteLine(double.Parse(data[0]) + double.Parse(data[1]));
return false;
}
}
public class Substract : ICommand
{
public bool Do(string[] data)
{
Console.WriteLine(double.Parse(data[0]) - double.Parse(data[1]));
return false;
}
}
But I was unable to find an how to do this in Ninject.
As in the link provided, you are intending to look up a value by Key.
What you are searching for is called named binding. Bindings are Identified by a Name. How ever the Problem here is, that you need to use the common injection strategies of ninject.
Bind<IDeviceState>().To<OnlineState>().Named("Online");
Bind<IDeviceState>().To<OfflineState>().Named("Offline");
public Modem([Named("Online")] IDeviceState state){
_state = state;
}
This way, you can choose which implementation of IDeviceState will be injected by the NamedAttribute, which is added right before the injection parameter. But this doesn't fully work out for you, because you want to create IDeviceStates on the fly. Thats why you need to use the Ninject.Extensions.Factory.
This will allow you to Inject a IDeviceStateFactory.
public interface IDeviceStateFactory
{
IDeviceState GetOnline();
IDeviceState GetOffline();
}
Those Factorys underlie a very specific syntax, where Get-Methods will resolve a Named Binding as described above. So GetOnline() will match the Bind<IDeviceState>().To<OnlineState>().Named("Online") binding and return an instance of OnlineState.
Just tell the IoCContainer that IDeviceStateFactory is a factory. An implementation of that interface will then automatically be provided by Ninject's Proxy system.
Bind<IDeviceStateFactory>().ToFactory();
So finally this is how you could imlpement your class Modem using this technique
public class Modem : IHardwareDevice
{
IDeviceStateFactory _stateFactory;
IDeviceState _currentState;
public Modem(IDeviceStateFactory stateFactory)
{
_stateFactory = stateFactory;
SwitchOn();
}
void SwitchOn()
{
_currentState = _stateFactory.GetOnline();
}
}
Using a real Key
However if you really want to use your DeviceState-Enumeration like before, you could use the approach described here.
The Binding Would look pretty much like this:
const string EnumKey = "EnumKey";
Bind<IDeviceState>().To<OnlineState>()
.WithMetadata(EnumKey, DeviceState.Online);
Use this Method to resolve using DeviceState.Online Key
IResolutionRoot.Get<IDeviceState>(x => x.Get<DeviceState>(EnumKey) == DeviceState.Online);
But in my opinion, there is no reason to do such complicated thing. I recommend you to just forget about the whole IIndex<TKey, TSource> mechanics from Autofac and do it the ninject way.
Your Edit: preserving IIndex (Solution involving Factory Extension)
Well, as IIndex and no such thing do exist in Ninject, you could create your own implementation of it, Inheriting from IDictionary, or just define it much alike it and only defining it as follows:
public interface IIndex<TKey, TValue>
{
bool TryGetValue(TKey key, out TValue value);
TValue this[TKey key] { get; set; }
}
The Factory from above then gets ICommandFactory
public interface ICommandFactory
{
ICommand GetAdd();
ICommand GetSubtract();
}
then you only need to create an implementation of IIndex using the ICommandFactory to resolve the actual command instances.
public class CommandIndex : IIndex<string, ICommand>
{
private readonly ICommandFactory _factory;
public CommandIndex(ICommandFactory factory)
{
_factory = factory;
}
public bool TryGetValue(string key, out ICommand value)
{
switch (key)
{
case "Add":
value = _factory.GetAdd();
break;
case "Subtract":
value = _factory.GetSubtract();
break;
default:
value = null;
break;
}
return value != null;
}
public ICommand this[string key]
{
get
{
ICommand value;
TryGetValue(key, out value);
return value;
}
set { throw new NotSupportedException();}
}
}
But I really need to ask you: Is this whole thing necessary? Man just use the factory. It really gets much less complicated.
Another attempt of preserving IIndex without Factory Extension
Another Attempt with propably less coding is directly using the IKernel which is propably a slightly bad practice. However you can then resolve named bindings like this:
public class NamedBindingIndex<TValue> : IIndex<string, TValue>
{
private readonly IKernel _kernel;
public NamedBindingIndex(IKernel kernel)
{
_kernel = kernel;
}
public bool TryGetValue(string key, out TValue value)
{
value = _kernel.Get<TValue>(key); // eventually catch an Exception here
return value != null;
}
public TValue this[string key]
{
get
{
TValue value;
TryGetValue(key, out value);
return value;
}
set { throw new NotSupportedException(); }
}
}
Just bind it like this
Bind<IIndex<string, ICommand>>().To<NamedBindingIndex<ICommand>>();
And then your Solution should be working pretty much as same. Another plus is, that this very last attempt doesn't need no Ninject.Extensions.Factory.
For anyone else with a similar problem I was still unable to find anything similar to IIndex and this was as close as I could do.
public static class NinjectExtender
{
public const string Index = "INDEX";
public static IBindingWithOrOnSyntax<TImplementation> Keyed<T, TImplementation, TKey>(this IKernel binding, TKey key) where TImplementation : T
{
if (!binding.CanResolve<IIndex<TKey, T>>())
{
binding.Bind<IIndex<TKey, T>>().ToMethod(context => new Index<TKey,T>(context));
}
return binding.Bind<T>().To<TImplementation>().WithMetadata(Index, key);
}
}
public class Index<T, M> : IIndex<T, M>
{
private readonly IContext context;
public Index(IContext context)
{
this.context = context;
}
public bool TryGetValue(T key, out M value)
{
try
{
value = this[key];
return true;
}
catch (KeyNotFoundException)
{
value = default(M);
return false;
}
}
public M this[T key]
{
get
{
try
{
var service = context.Kernel.Get<M>(binding => binding.Get<T>(NinjectExtender.Index).Equals(key));
if (!service.Equals(default(M)))
{
return service;
}
else
{
throw new KeyNotFoundException();
}
}
catch (Exception)
{
throw new KeyNotFoundException();
}
}
}
}
I am a bit unsure in if the context is handled in the same way as Autofac but I am not having issues as of now.
kernel.Keyed<ICommand, Add, string>("add");

Exception thrown: 'System.MissingMethodException'

I'm working in a WinForm app in 4 layers:
DAL (Data access)
BOL (Bussiness objects)
BAL (Bussiness access)
INT (Intermediate access).
I'm using the Intermediate layer to run any operation needed by the Presentation layer, trying to make it independent, as we can use it in a WinForm, ASP, and so.
I've created a Class that executes those operations like this:
// Clase: ProjectStatusMID
using System.Collections.Generic;
namespace Trevo.FrameWork
{
public class ProjectStatusMID
{
#region Propiedades
private ProjectStatusBOL _Data = new ProjectStatusBOL();
private ProjectStatusBAL _Operations = new ProjectStatusBAL();
private Acciones _Action = Acciones.Nada;
#endregion Propiedades
public ProjectStatusBOL Data
{
get { return _Data; }
set
{
_Data = value;
}
}
public ProjectStatusBAL Operations
{
get { return _Operations; }
set
{
_Operations = value;
}
}
public Acciones Action
{
get { return _Action; }
set
{
_Action = value;
}
}
public int IDProject
{
get { return _Data.IDProject; }
set
{
_Data.IDProject = value;
}
}
public List<Codigos> ProjectsList
{
get { return LoadProjects(); }
}
public ProjectStatusMID()
{
//Load();
}
public void Load()
{
Operations.Consultar(Data);
}
public List<Codigos> LoadProjects()
{
List<Codigos> oRet = new List<Codigos>();
MyProjectsBAL _Operations = new MyProjectsBAL();
MyProjectsBOL _Data = new MyProjectsBOL();
List<MyProjectsBOL> _MyList = _Operations.Lista(_Data);
foreach (MyProjectsBOL o in _MyList)
{
oRet.Add(new Codigos(o.IDProject, o.Project));
}
return oRet;
}
}
}
// Clase: ProjectStatusMID
At the front-end (in this case is WinForm), we are instancing this class as follows:
ProjectStatusMID OO = new ProjectStatusMID();
So, the issue comes when calling one of the methods:
parProject.DataSource = OO.LoadProjects();
Everything is referenced, the app compiles without any problems, the project that contains the class is part of the solution in a separated project (as any other layer), BUT we have the following error:
System.MissingMethodException occurred
HResult=-2146233069
Message=Método no encontrado: 'System.Collections.Generic.List`1 Trevo.FrameWork.ProjectStatusMID.LoadProjects()'.
Source=WorkLoadPresentation
StackTrace:
en Trevo.FrameWork.PS_ProjectStatus_Datos.CargarListas()
en Trevo.FrameWork.PS_ProjectStatus_Datos.PS_ProjectStatus_Datos_Load(Object sender, EventArgs e) en C:\Users\fbravo\OneDrive\Particular_Sistemas\WorkLoad\WorkLoadPresentation\ProjectStatus\PS_ProjectStatus_Datos.cs:línea 25
InnerException:
I've tried to make the class static, re-creating the entire app, deleting the GAC, and so, but a week loose trying different things.
Any help will be appreciated
Could be several issues. The most common one is that you included the DLL library which is the wrong version (e.g. without the method that's missing). Easiest thing to do is to open the exe in the decompiler (e.g. Reflector) and step through it.
Another issue could be the wrong bitness (but probably not).
You have to make sure you referenced the external project dll in your main Winforms application

Entity Framework Tracing provider wrapper without config files

I would like to use Entity Framework Code first approach with SQLCE4 database. Everything seems to be really nice but I have problem with debugging sql queries. I found that EFTracing from http://efwrappers.codeplex.com/ should be exactly what I need but I don't know how to use it without app.config file. I am not big fan of this configuration. I want to use only C# code to set everything up and running. I think it should be fine to use code like this:
using (System.Data.Common.DbConnection c =
new EFTracingProvider.EFTracingConnection(
new System.Data.SqlServerCe.SqlCeConnection(conn)))
{
using (var context = new MyContext(c))
{
var a = from data in context.Projects select data;
}
}
But it doesn't work. It throws exception:
Unable to determine the provider name for connection of type
EFTracingProvider.EFTracingConnection'.
Is there any simple way how to correctly create wrapped connection only in code?
Solution for my problem is following DbContext object.
public class MyContext : DbContext
{
public MyContext()
: base(CreateConnection("Data Source=file.sdf",
"System.Data.SqlServerCe.4.0"), true)
{ }
public DbSet<Project> Projects { get; set; }
public static bool TraceEnabled = true;
private static DbConnection CreateConnection(string connectionString,
string providerInvariantName)
{
DbConnection connection = null;
if (TraceEnabled)
{
EFTracingProviderConfiguration.RegisterProvider();
EFTracingProviderConfiguration.LogToConsole = true;
string wrapperConnectionString = String.Format(#"wrappedProvider={0};{1}",
providerInvariantName, connectionString);
connection = new EFTracingConnection()
{
ConnectionString = wrapperConnectionString
};
}
else
{
DbProviderFactory factory = DbProviderFactories.GetFactory(providerInvariantName);
connection = factory.CreateConnection();
connection.ConnectionString = connectionString;
}
return connection;
}
}
So now I can use just context and connection is created automatically for wrapped or unwrapped SqlCe depending on TraceEnabled property.
using (var context = new MyContext())
{
var a = context.Projects.FirstOrDefault();
}
The genuine way to trace SQL queries is to call the ToString method like that :
var t = from c in _entities.CompanyDetail
select c;
string test = t.ToString();
I don't know EFTracing, but you might want to try MVCMiniProfiler. Despite the name MVCMiniProfiler also provide SQL queries profiling and work without config file.
I've done this by creating a wrapper class around the ObjectContext and using that wrapper instead of the original context. Here's an example context wrapper:
public partial class LoggedContext : MyContext
{
public LoggedContext()
: this("name=MyEntities") // Adjust this to match your entities
{
}
public LoggedContext(string connectionString)
: base(EntityConnectionWrapperUtils.CreateEntityConnectionWithWrappers(connectionString)
{
}
private EFTracingConnection TracingConnection
{
get { return this.UnwrapConnection<EFTracingConnection>(); }
}
public event EventHandler<CommandExecutionEventArgs> CommandExecuting
{
add { this.TracingConnection.CommandExecuting += value; }
remove { this.TracingConnection.CommandExecuting -= value; }
}
public event EventHandler<CommandExecutionEventArgs> CommandFinished
{
add { this.TracingConnection.CommandFinished += value; }
remove { this.TracingConnection.CommandFinished -= value; }
}
public event EventHandler<CommandExecutionEventArgs> CommandFailed
{
add { this.TracingConnection.CommandFailed += value; }
remove { this.TracingConnection.CommandFailed -= value; }
}
}
I also have a static class that defines the tracing output method and has a static method to initialize tracing. Here:
public static class EFTracingExtensions
{
private static ILogger _logger;
public static void InitSqlTracing(ILogger logger)
{
_logger = logger;
EFTracingProviderConfiguration.RegisterProvider();
if (logger.IsLoggingEnabled()) // Don't add logging hooks if logging isn't enabled
{
EFTracingProviderConfiguration.LogAction = new Action<CommandExecutionEventArgs>(AppendSqlLog);
}
}
private static void AppendSqlLog(CommandExecutionEventArgs e)
{
if (e.Status != CommandExecutionStatus.Executing) // we only care about Finished and Failed
{
StringBuilder msg = new StringBuilder(e.ToTraceString().TrimEnd());
msg.Append(Environment.NewLine);
if (e.Result is SqlDataReader)
{
int rows = ((SqlDataReader)e.Result).HasRows ? ((SqlDataReader)e.Result).RecordsAffected : 0;
msg.AppendFormat("*** {0} rows affected", rows);
}
else if (e.Result is int)
{
msg.AppendFormat("*** result: {0}", e.Result);
}
else
{
msg.AppendFormat("*** finished, result: {0}", e.Result);
}
msg.Append(Environment.NewLine);
msg.AppendFormat(" [{0}] [{1}] in {2} seconds", e.Method, e.Status, e.Duration);
_logger.Log(msg.ToString(), LoggerCategories.SQL);
}
}
}
ILogger is the logging interface I'm using. You need to substitute your own interface/methods.
The InitSqlTracing method is invoked once when my program starts up, and then the LoggedContext class is used to log all the SQL generated by Entity Framework.
Putting it all together with your sample code:
EFTracingExtensions.InitSqlTracing(logger); // only call this once
using (var context = new LoggedContext())
{
var a = from data in context.Projects select data;
}

Object Context, Repositories and Transactions

I was wondering what the best way to use transations with the entity framework.
Say I have three repositories:
Repo1(ObjectContext context)
Repo2(ObjectContext context)
Repo3(ObjectContext context)
and a service object that takes the three repositories:
Service(Repo1 repo1,Repo2 repo2, Repo3 repo3)
Serive.CreateNewObject <- calls repo1, repo2, repo3 to do stuff.
So when I create the service I create three repositories first and pass them down, each repositry takes a object context so my code looks something like this:
MyObjectContext context = new MyObjectContext();
Repo1 repo = new Repo1(context);
// etc
Now I have a controller class that is responsible for calling different services and compants of my application, showing the right forms etc. Now what I want to be able to do is wrap everything that happens in one of the controller methods in a transaction so that if some thing goes wrong I can rollback back.
The controller takes a few different Service objects, but doesn't know anything about the object context.
My questions are:
Should the context be passed in to the service layer also.
How do I implement a transaction in the controller so that anything that happens in the service
layers arn't commited untill everything has passed.
Sorry if it's a bit hard to understand..
Why doesn't your controller know about the ObjectContext?
This is where I would put it. Check out - http://msdn.microsoft.com/en-us/magazine/dd882510.aspx - here the Command is what will commit/rollback the UnitOfWork(ObjectContext).
If you don't want to have your Controller know exactly about the EF (good design) then you want to abstract your ObjectContext into an interface similar to the approach in the above link.
How about using a custom TransactionScope, one that commits when all of your services have committed?
public class TransactionScope : Scope<IDbTransaction>
{
public TransactionScope()
{
InitialiseScope(ConnectionScope.CurrentKey);
}
protected override IDbTransaction CreateItem()
{
return ConnectionScope.Current.BeginTransaction();
}
public void Commit()
{
if (CurrentScopeItem.UserCount == 1)
{
TransactionScope.Current.Commit();
}
}
}
So the transaction is only committed when the UserCount is 1, meaning the last service has committed.
The scope classes are (shame we can't do attachements...):
public abstract class Scope<T> : IDisposable
where T : IDisposable
{
private bool disposed = false;
[ThreadStatic]
private static Stack<ScopeItem<T>> stack = null;
public static T Current
{
get { return stack.Peek().Item; }
}
internal static string CurrentKey
{
get { return stack.Peek().Key; }
}
protected internal ScopeItem<T> CurrentScopeItem
{
get { return stack.Peek(); }
}
protected void InitialiseScope(string key)
{
if (stack == null)
{
stack = new Stack<ScopeItem<T>>();
}
// Only create a new item on the stack if this
// is different to the current ambient item
if (stack.Count == 0 || stack.Peek().Key != key)
{
stack.Push(new ScopeItem<T>(1, CreateItem(), key));
}
else
{
stack.Peek().UserCount++;
}
}
protected abstract T CreateItem();
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// If there are no users for the current item
// in the stack, pop it
if (stack.Peek().UserCount == 1)
{
stack.Pop().Item.Dispose();
}
else
{
stack.Peek().UserCount--;
}
}
// There are no unmanaged resources to release, but
// if we add them, they need to be released here.
}
disposed = true;
}
}
public class ScopeItem<T> where T : IDisposable
{
private int userCount;
private T item;
private string key;
public ScopeItem(int userCount, T item, string key)
{
this.userCount = userCount;
this.item = item;
this.key = key;
}
public int UserCount
{
get { return this.userCount; }
set { this.userCount = value; }
}
public T Item
{
get { return this.item; }
set { this.item = value; }
}
public string Key
{
get { return this.key; }
set { this.key = value; }
}
}
public class ConnectionScope : Scope<IDbConnection>
{
private readonly string connectionString = "";
private readonly string providerName = "";
public ConnectionScope(string connectionString, string providerName)
{
this.connectionString = connectionString;
this.providerName = providerName;
InitialiseScope(string.Format("{0}:{1}", connectionString, providerName));
}
public ConnectionScope(IConnectionDetailsProvider connectionDetails)
: this(connectionDetails.ConnectionString, connectionDetails.ConnectionProvider)
{
}
protected override IDbConnection CreateItem()
{
IDbConnection connection = DbProviderFactories.GetFactory(providerName).CreateConnection();
connection.ConnectionString = connectionString;
connection.Open();
return connection;
}
}
Wrap the operation in a TransactionScope.
You might want to implement the transaction model used by the Workflow Foundation. It basically has an interface that all "components" implement. After each does the main work successfully, then the host calls the "commit" method on each. If one failed, it calls the "rollback" method.

Categories

Resources