NServiceBus Upgrade from v3 to v4: OracleMessageModule.Begin() is not called - upgrade

Working code before upgrade. HandleBeginMessage() is called automatically:
public class OracleMessageModule : IMessageModule
{
public OracleMessageModule()
{
Factory = new OracleSagaSessionFactory();
}
public OracleSagaSessionFactory Factory { get; set; }
public void HandleBeginMessage()
{
Factory.Begin();
}
public void HandleEndMessage()
{
Factory.Complete();
}
public void HandleError()
{
Factory.Complete();
}
}
Code not working anymore after upgrade to v4. Begin() is not called autommatically:
public class OracleMessageModule : UnitOfWork.IManageUnitsOfWork
{
public OracleMessageModule()
{
Factory = new OracleSagaSessionFactory();
}
public OracleSagaSessionFactory Factory { get; set; }
public void Begin()
{
Factory.Begin();
}
public void End(System.Exception ex = null)
{
Factory.Complete();
}
}

IManageUnitsOfWork are not autoregistered. You need to register your unit of work explicitly.
For more details on how to, see here:
http://docs.particular.net/nservicebus/unit-of-work-in-nservicebus#registering-your-unit-of-work

Related

UnitOfWork with Unity DI Not Persisting Context Changes

I am trying to set up UoW with Unity DI using .NET Framework, and everything works until I call the context.SaveChanges(), the ChangeTracker.HasChanges() in the context passed to the UoW shows false, so context changes are not persisting through to the UoW implementation. I have a feeling this is due to my registration of the UoW in the Unity container, as this is my first time setting this up. Does anything stand out as incorrect?
EDIT - I went around the UoW functionality and attempted to just call _context.SaveChanges() directly on my context and it still does not save. So it seems it's something beyond the UoW.
UnityConfig
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<AccountController>(new InjectionConstructor());
container.RegisterType<IChildFamilyCareProviderLinkRepository, ChildFamilyCareProviderLinkRepository>();
container.RegisterType<IFamilyCareProviderRepository, FamilyCareProviderRepository>();
container.RegisterType<IFamilyCareProviderContactRepository, FamilyCareProviderContactRepository>();
container.RegisterType<IUnitOfWork, UnitOfWork>();
container.RegisterInstance(AutoMapperConfig.Mapper);
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
UnitOfWork
public class UnitOfWork : IUnitOfWork
{
private readonly RAINContext _context;
public IFamilyCareProviderRepository FamilyCareProviders { get; private set; }
public IFamilyCareProviderContactRepository FamilyCareProviderContacts { get; private set; }
public IChildFamilyCareProviderLinkRepository ChildFamilyCareProviderLinks { get; private set; }
public UnitOfWork(RAINContext context,
IFamilyCareProviderRepository familyCareProviderRepository,
IFamilyCareProviderContactRepository familyCareProviderContactRepository,
IChildFamilyCareProviderLinkRepository childFamilyCareProviderLinkRepository)
{
this._context = context;
this.FamilyCareProviders = familyCareProviderRepository;
this.FamilyCareProviderContacts = familyCareProviderContactRepository;
this.ChildFamilyCareProviderLinks = childFamilyCareProviderLinkRepository;
}
public bool Save()
{
_context.ChangeTracker.HasChanges(); //THIS SHOWS FALSE
var success = _context.SaveChanges(); //No changes are saved to DB
return success > 0;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool dispose)
{
if (dispose)
{
_context.Dispose();
}
}
}
IUnitOfWork
public interface IUnitOfWork : IDisposable
{
IFamilyCareProviderRepository FamilyCareProviders { get; }
IFamilyCareProviderContactRepository FamilyCareProviderContacts { get; }
IChildFamilyCareProviderLinkRepository ChildFamilyCareProviderLinks { get; }
bool Save();
}
Controller
public class FamilyCareProviderController : Controller
{
private readonly IUnitOfWork _unitOfWork;
private readonly IMapper _mapper;
public FamilyCareProviderController(
IUnitOfWork unitOfWork)
{
this._unitOfWork = unitOfWork;
this._mapper = AutoMapperConfig.Mapper;
}
[HttpPost]
public ActionResult CreateFamilyCareProvider(CreateFamilyCareProvider vm)
{
try
{
var fcp = new FamilyCareProvider()
{
Id = Guid.NewGuid().ToString().ToUpper(),
FamilyCareProviderName = vm.FamilyCareProviderName,
IsActive = true,
CreatedById = UserId,
LastUpdatedById = UserId
};
_unitOfWork.FamilyCareProviders.Insert(fcp);
var fcpc = _mapper.Map<FamilyCareProviderContact>(vm.FamilyCareProviderContact);
_unitOfWork.FamilyCareProviderContacts.Insert(fcpc);
var result = _unitOfWork.Save();
return RedirectToAction(nameof(Index));
}
catch (Exception)
{
ModelState.AddModelError("", "Error saving family care provider contact.");
return View(vm);
}
}
}
Is there something that is obvious that stands out in the implementation of this?

MEF ImportMany simple plugin

IPlugin Calss Library
namespace IPlugin
{
public interface IPlugin
{
string Name { get; set; }
void Start();
void Stop();
}
[Export(typeof(IPlugin))]
public abstract class BasePlugin:IPlugin
{
private string _name;
public BasePlugin()
{
Name = "Base Plugin";
}
public string Name
{
get { return _name; }
set { _name = value; }
}
public virtual void Start()
{
fnDowWork();
}
protected abstract void fnDowWork();
public virtual void Stop()
{
}
}
}
Test Plugin Class Library
namespace TestPlugin
{
public class TestPlugin:IPlugin.BasePlugin
{
public TestPlugin()
{
Name = "Test Plugin";
}
protected override void fnDowWork()
{
Console.WriteLine("Do Work !");
}
}
}
Console Application
class Program
{
static void Main(string[] args)
{
var app = new MyApp();
foreach (var p in app._Plugins)
{
p.Start();
}
}
}
public class MyApp
{
[ImportMany(typeof(IPlugin.IPlugin))]
public IEnumerable<IPlugin.IPlugin> _Plugins;
public string _PluginFolder { get; set; }
public string _StartupPath { get; set; }
public MyApp()
{
_StartupPath = Environment.CurrentDirectory;
var pluginFolderName = System.Configuration.ConfigurationManager.AppSettings["PluginFolder"];
_PluginFolder = System.IO.Path.Combine(_StartupPath, pluginFolderName);
InitializeMEF();
}
private void InitializeMEF()
{
var dirCatalog = new DirectoryCatalog(_PluginFolder, "*.dll");
CompositionContainer container = new CompositionContainer(dirCatalog);
container.ComposeParts(this);
}
}
the DirectoryCatalog find tow Assembly IPlugin.dll and TestPlugin.dll and after Compose parts
the myApp._Plugins is not null but its empty , i don't know where i am doing wrong!
You will need to use the InheritedExportAttribute instead of the ExportAttribute:
[InheritedExport(typeof(IPlugin))]
public abstract class BasePlugin:IPlugin
Note that this will only work for plugins that derive from BasePlugin. Other implementations of IPlugin will not be marked for export. To do this you will have to decorate the interface instead.

Instance in Caliburn Micro

We are using Caliburn Micro for the first time.
We have a AppBootstrapper inherited from ShellViewModel.
Situvation is that VieModels should have the same instance unless it is reset.
we are able to achieve shared or not shared everytime, but releasing the export whenever needed is still a mystery.
public class AppBootstrapper : Bootstrapper<ShellViewModel>
{
private static CompositionContainer _container;
protected override void Configure()
{
try
{
_container = new CompositionContainer(
new AggregateCatalog(AssemblySource.Instance.Select(x => new AssemblyCatalog(x))));
var batch = new CompositionBatch();
batch.AddExportedValue<IWindowManager>(new WindowManager());
batch.AddExportedValue<IEventAggregator>(new EventAggregator());
batch.AddExportedValue(_container);
StyleManager.ApplicationTheme = ThemeManager.FromName("Summer");
_container.Compose(batch);
}
catch (Exception exception)
{
}
}
public static void ReleaseAll()
{
}
protected override object GetInstance(Type serviceType, string key)
{
try
{
var contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(serviceType) : key;
var exports = _container.GetExportedValues<object>(contract);
if (exports.Any())
return exports.First();
throw new Exception(string.Format("Could not locate any instances of contract {0}.", contract));
}
catch (ReflectionTypeLoadException ex)
{
foreach (Exception inner in ex.LoaderExceptions)
{
// write details of "inner", in particular inner.Message
}
return null;
}
}
protected override IEnumerable<object> GetAllInstances(Type serviceType)
{
try
{
return _container.GetExportedValues<object>(AttributedModelServices.GetContractName(serviceType));
}
catch (Exception exception)
{
return null;
}
}
protected override void BuildUp(object instance)
{
_container.SatisfyImportsOnce(instance);
}
}
ShellViewModel
[Export(typeof(ShellViewModel))]
public sealed class ShellViewModel : Conductor<IScreen>.Collection.OneActive, IHandle<object>
{
[ImportingConstructor]
public ShellViewModel(CompositionContainer compositionContainer, IEventAggregator eventAggregator)
{
CompositionContainer = compositionContainer;
EventAggregator = eventAggregator;
eventAggregator.Subscribe(this);
Items.Add(compositionContainer.GetExportedValue<AViewModel>());
Items.Add(compositionContainer.GetExportedValue<BViewModel>());
ActivateItem(Items.Single(p => p.DisplayName == AppMessageType.A.ToString()));
}
public IEventAggregator EventAggregator { get; set; }
public CompositionContainer CompositionContainer { get; set; }
public void Handle(object message)
{
//throw new System.NotImplementedException();
}
public void B()
{
ActivateItem(Items.Single(p => p.DisplayName == AppMessageType.B.ToString()));
}
public void A()
{
ActivateItem(Items.Single(p => p.DisplayName == AppMessageType.A.ToString()));
}
public void RESET()
{
AppBootstrapper.ReleaseAll();
ActivateItem(Items.Single(p => p.DisplayName == AppMessageType.A.ToString()));
}
public enum AppMessageType
{
A,
B
}
}
AViewModel
[Export(typeof(AViewModel))]
public sealed class AViewModel : Conductor<IScreen>.Collection.OneActive, IHandle<object>
{
[ImportingConstructor]
public AViewModel(CompositionContainer compositionContainer, IEventAggregator eventAggregator)
{
DisplayName = ShellViewModel.AppMessageType.A.ToString();
CompositionContainer = compositionContainer;
EventAggregator = eventAggregator;
eventAggregator.Subscribe(this);
}
public IEventAggregator EventAggregator { get; set; }
public CompositionContainer CompositionContainer { get; set; }
public void Handle(object message)
{
//throw new System.NotImplementedException();
}
}
BViewModel
[Export(typeof(BViewModel))]
public sealed class BViewModel : Conductor<IScreen>.Collection.OneActive, IHandle<object>
{
[ImportingConstructor]
public BViewModel(CompositionContainer compositionContainer, IEventAggregator eventAggregator)
{
DisplayName = ShellViewModel.AppMessageType.B.ToString();
CompositionContainer = compositionContainer;
EventAggregator = eventAggregator;
eventAggregator.Subscribe(this);
}
public IEventAggregator EventAggregator { get; set; }
public CompositionContainer CompositionContainer { get; set; }
public void Handle(object message)
{
//throw new System.NotImplementedException();
}
}
Now AViewModel and BViewModel have single instance.
Whenever Release Button is clicked i want to have new instance of AViewModel and BViewModel.
Hoping to get a reply soon.
Regards,
Vivek
When working with an IoC container, the only part of your code that should take it as a dependency should be your composition root (i.e. your AppBootstrapper in this case). You shouldn't be injecting or referencing the container anywhere else in your code (except possibly factories).
If you want your ShellViewModel to control the lifetime of your child view models (A and B), then you should consider injecting view model factories into your ShellViewModel (via constructor injection if they are required dependencies).
Your AViewModelFactory would just have a single Create method that returns a new instance of AViewModel, likewise with the BViewModelFactory. You can simply new up your view models directly in the factories. If your view models have large dependency chains themselves, then you could consider adding a reference to your container in the factories, although preferably consider looking into the MEF ExportFactory<T> type.

Many operations with DataContext

I'm using EF for developing and enough new here.
I'm confused with how to work with EntityFramework context when I have to do different operations with context. Could you give me good tutorials and glance at my code for finding possible issues
Now I have next code
//domain.dll
class OrderDomainService
{
public void DoWork()
{
foreach(var order in GetOrders())
{
DeleteOrder(order);
}
}
public List<Order> GetOrders()
{
IOrderRepository orderRep = new OrderRepository();
return orderRep.GetAll();
}
public void DeleteOrder(Order order)
{
IOrderRepository orderRep = new OrderRepository();
return orderRep.Delete(order);
}
}
//repository.dll
public interface IOrderRepository
{
List<Order> GetAll();
void Delete(Order order);
void SaveContext()
}
public class OrderRepository
{
public OrderRepository()
{
if (ctx == null)
ctx = new EntityFrameworkDataContext();
}
static EntityFrameworkDataContext ctx { get; set; }
public List<Order> GetAll()
{
return ctx.Orders;
}
public void Delete(Order order)
{
ctx.Orders.Delete(order);
}
public void SaveContext()
{
ctx.SaveChanges();
ctx = null;
}
}
You need to share same EntityFrameworkDataContext instance between between several repositories (Use unit of work pattern http://blogs.msdn.com/b/adonet/archive/2009/06/16/using-repository-and-unit-of-work-patterns-with-entity-framework-4-0.aspx ).Because if you are doing an operaiton which you need to initiate two or more repositories you will have problems.

MEF Custom attributes and Lazy

I think I am losing my mind. :)
I've been struggling with this for two days now. The code looks right. But for some reason when I try to access the [ImportMany] field, it is null, or at least not returning any values.
It get the 3 parts in the catalog, but they don't get applied to the Lazy[] import I am defining.
Here's my code:
using System;
using System.Linq;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
namespace MefTest
{
// Extension interface and metadata
public interface IUIExtension
{
void DoSomething();
}
public interface IUIExtensionDetails
{
string Name { get; }
string Uri { get; }
}
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false)]
public class UIExtensionAttribute : ExportAttribute
{
public UIExtensionAttribute() : base(typeof(IUIExtensionDetails)) { }
public string Name { get; set; }
public string Uri { get; set; }
}
// Extensions
[UIExtension(Name="Test 01", Uri="http://www.yourmomma.com/")]
public class Test1Extension : IUIExtension
{
public void DoSomething() { }
}
[UIExtension(Name = "Test 02", Uri = "http://www.yourdaddy.com/")]
public class Test2Extension : IUIExtension
{
public void DoSomething() { }
}
[UIExtension(Name = "Test 03", Uri = "http://www.youruncle.com/")]
public class Test3Extension : IUIExtension
{
public void DoSomething() { }
}
// Main program
public class Program
{
static void Main(string[] args)
{
Program p = new Program();
p.Run();
}
[ImportMany]
public Lazy<IUIExtension, IUIExtensionDetails>[] Senders { get; set; }
public void Run()
{
Compose();
}
public void Compose()
{
var catalog = new AssemblyCatalog(
System.Reflection.Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
// This is always 3
Console.WriteLine(
(from g in container.Catalog.Parts select g).Count());
// This is always 0
Console.WriteLine(Senders.Length);
Console.ReadKey();
}
}
}
Your error is here:
public UIExtensionAttribute() : base(typeof(IUIExtensionDetails))
You should pass the contract type there, not the metadata type:
public UIExtensionAttribute() : base(typeof(IUIExtension))
(Also, in order to make sure that your custom export class has the right properties as expected by the import with metadata, I would make it implement the IUIExtensionDetails interface. But that is not mandatory.)
Your metadata attribute is defining the exports as typeof(IUIExtensionDetails) which is your metadata contract, not your actual extension. Change the custom attribute constructor to:
public UIExtensionAttribute() : base(typeof(IUIExtension)) { }