Autofac registration with multiple assembies and differing EntityConnections - entity-framework

We have two Assemblies that contain their own Entity-Framework EDMX & repositoriy objects. These are registered using Autofac in an ASP.NET webapplication.
These Assemblies are very similar of architecture (but differing EDMX) we have found that the last EntityConnection being registered is the EntityConnection that is being used in both Assemblies. We need to limit the usage of an EntityConnection to only be used by Types of an assembly or namespace.
var assembly = typeof(Activity).Assembly;
builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces();
builder.Register(reg => new EntityConnection(ConnectionString));
var assembly = typeof(User).Assembly;
builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces();
builder.Register(reg => new EntityConnection(ConnectionString));
Is there a way to register the EntityConnection and limit the depth of EntityConnection? Limit each EntityConnection to the assembly it belong to?
Here's a pseudocode example of how we want to register EntityConnection for use in only an assembly or namespace.
builder.Register(reg => new EntityConnection(ConnectionString)).ForNamespace("x");

try to solve the problem at an higher level of abstraction. Since you have two separate domains (one containing the Activity entity, and one containing the User entity), it would be convenient to have this explicitly in your application design. For instance, define a factory of some kind per domain:
public interface IActivityDomainContextFactory
{
ObjectContext CreateNew();
}
public interface IPeopleDomainContextFactory
{
ObjectContext CreateNew();
}
You can now easily create an implementation for each interface, register them in the Autofac ContainerBuilder and let your services depend on one of those interfaces, instead of depending them on a EntityConnection.
In this case you of course still have a dependency on the Entity Framework itself (see here for how to abstract that away), but this makes your configuration much easier, less fragile, better performing, and your application code more maintainable.
I hope this helps.

You probably want to name/key your registrations. See TypedNamedAndKeyedServices - Autofac
I think this solves half your problem, how to register the types. The other half is in the resolution. Since your doing autoregistration via assembly scanning, this might take a little more trickery.

There are plenty of good suggestions out there on improving this, so just recording my solution as a general sketch of how you'd do this in Autofac.
The trick is to use named services for the connections, then customise parameter resolution for types in each assembly so that the EntityConnection parameters get a named instance:
builder.Register(reg => new EntityConnection(ConnectionString))
.Named<EntityConnection>("activities");
builder.RegisterAssemblyTypes(typeof(Activity).Assembly)
.AsImplementedInterfaces()
.WithParameter(
(pi, c) => pi.ParameterType == typeof(EntityConnection),
(pi, c) => c.ResolveNamed<EntityConnection>("activities"));
builder.Register(reg => new EntityConnection(ConnectionString))
.Named<EntityConnection>("users");
builder.RegisterAssemblyTypes(typeof(User).Assembly)
.AsImplementedInterfaces()
.WithParameter(
(pi, c) => pi.ParameterType == typeof(EntityConnection),
(pi, c) => c.ResolveNamed<EntityConnection>("users"));

Related

How incapsulate dbquery into automapping profile

I try to pass from EF entity to dto in business layer.
So I setup Automapper and everything goes well.
Here is my profile class:
public DocumentProfile()
{
CreateMap<Data.Models.Docflow.Package, PackageDto>()
.ForMember(dest => dest.ReceiverName, opt => opt.MapFrom(src => src.Receiver.FullName))
.ForMember(dest => dest.SenderName, opt => opt.MapFrom(src => src.Sender.FullName))
;
}
But I make mapping from Package to PackageDto in different places of my code. And I have different specific queries in different cases. So I need to remember to include navigation properties Receiver and Sender in all queries.
So how can I incapsulate single query for Package entity with all necessary properties for certain projection?
I saw examples with value resolvers and type converters but it seems not suitable.
#lucian-bargaoanu, thanks for your comments!
Finally I came in to 2 suitable solutions.
Shared part is:
I prepare function like PackageDto Get(Guid packageId) in Repository and I incapulate dbquery with mapping to dto in repository and in BL I work only with dto.
But the difference is:
dbquery returns needed entity type in memory that is mapped then by Mapper.Map<>
dbquery returns IQueryable, that then extended by ProjectTo
Anyway It's necessary set profile with mapping rules, but second way is clearly as it performs includes that you need automatically.

Castle Windsor Lifestyle configuration

I've spent some time looking around, and there doesn't seem to be an obvious solution to this scenario.
I register all types from an assembly (that's about 80 types, interfaces are in separate assembly)
public static void RegisterAllFromAssemblies(string a)
{
IoC.Container.Register(
AllTypes.FromAssemblyNamed(a)
.Pick()
.WithService.FirstInterface()
.Configure(o => o.LifeStyle.PerWebRequest)
);
}
now say if i want to use a different LifeStyle for one of those objects, i can't override since i'll get the There is a component already registered for the given key error.
i've looked into various ways to modify the lifestyle after this registration, but so far haven't been able to make anything work.
what should be the ideal solution here? i'd prefer not to give up the AllTypes functionality.
i suppose i could specify a .Where filter when registering all and skip a few objects to be registered manually, but that's not a very enterprisey solution..
I believe you're talking about registering all of the types in an assembly where some of the types in the assembly might need to be registered with different lifestyles. So you've got IRepository which needs to be a PerWebRequest and ITypeMapper which can be a singleton.
I clarify because you could also mean that you want to have IRepository be a PerWebRequest at one spot in your code and a singleton in another spot. Without creating crazy lifestyles, you can create your component and register it for the default lifestyle. If you need another lifestyle sometimes you can create a new component and inherit from the existing one just for use in registration (the code sample shows this if this is confusing).
I wrote the sample so that it will work for either scenario and I gave a couple different approaches all focusing around the filtering abilities of configuring multiple items at once.
For this one, I'm calling out configuration for a particular component by type. It's not as "enerprisey" as you put it, but the intent is clearer if you only have a few exceptions to the rule. You'll note you can chain together configures. The unless is required because the second configure will pick up the component for the first configure being that my only condition is the services are based on IService. This assumes that castle processes the configures in order. I believe the assumption is sound, but haven't looked at the source for awhile.
container.Register(
Classes.FromThisAssembly()
.BasedOn<IService>()
.ConfigureFor<MyComponentAsSingleton>(component => component.LifestyleSingleton())
.Configure(component => component.LifestylePerWebRequest()).Unless(type => container.Kernel.GetAssignableHandlers(type).Count() > 0));
This one uses attributes to more generically deviate from the normal lifestyle "PerWebRequest
container2.Register(
Classes.FromThisAssembly()
.BasedOn<IService>()
.ConfigureIf(
//condition to check - do we have our custom Attribute?
registration => registration.Implementation.GetCustomAttributes(false).Any(attr => typeof(ShouldBeSingleton).IsAssignableFrom(attr.GetType())),
//if true register as singleton
component => component.LifestyleSingleton(),
//else register as per web request
component => component.LifestylePerWebRequest()
));
Now that I've given you a few samples that solve your immediate issue (as I understand it) let me give you my advice for free!
First I don't really like WithService.FirstInterface(). As the intelisense states it's non-deterministic when you implement multiple interfaces. Any dev could come in and make a harmless interface change to a class and then break the system. If you can get away with WithService.DefaultInterfaces() you'd have a harder to mess up solution. Default interfaces is just telling castle that when registering the Foo component, use the service IFoo if it implements an interface named IFoo.
Second, I believe if you partition your registration logic into cohesive units you probably wouldn't have run into this problem. The key is to have many installer files that implement IWindsorInstaller. Inside of these installers you only register (using the Classes or Types to keep it enterprisey still) types that make sense for the particular installer. The chances that you have multiple lifestyle concerns in the same installer is pretty low (and if you find this, you probably need more installers)
If you followed this approach you could end up with a RepositoryInstaller, ViewInstaller, ControllerInstaller, etc. More on installers can be found on the castle documentation site
What you could do if you wanted is then have a common boostrapper for all your systems that looks into the application directory and installs all of the installers that are in the directory. Being this wasn't what you asked I'll stop elaborating, but if interested you can ping me and I can show you more about what I'm talking about.
Full sample code as a console app:
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MultipleLifecyles
{
[AttributeUsage(AttributeTargets.Class)]
public class ShouldBeSingleton : Attribute
{
}
public interface IService
{
void DoSomething();
}
public class MyComponent : IService
{
public void DoSomething()
{
throw new NotImplementedException();
}
}
[ShouldBeSingleton]
public class MyComponentAsSingleton : MyComponent
{
}
class Program
{
static void Main(string[] args)
{
//option 1
IWindsorContainer container = new WindsorContainer();
container.Register(
Classes.FromThisAssembly()
.BasedOn<IService>()
.ConfigureFor<MyComponentAsSingleton>(component => component.LifestyleSingleton())
.Configure(component => component.LifestylePerWebRequest()).Unless(type => container.Kernel.GetAssignableHandlers(type).Count() > 0));
IWindsorContainer container2 = new WindsorContainer();
container2.Register(
Classes.FromThisAssembly()
.BasedOn<IService>()
.ConfigureIf(
//condition to check - do we have our custom Attribute?
registration => registration.Implementation.GetCustomAttributes(false).Any(attr => typeof(ShouldBeSingleton).IsAssignableFrom(attr.GetType())),
//if true register as singleton
component => component.LifestyleSingleton(),
//else register as per web request
component => component.LifestylePerWebRequest()
));
Console.ReadLine();
}
}
}
Is it an option for you register manually the exceptions first? If so, components manually registered will not be re-registered by "AllTypes"(I suggest you to use Classes instead).
If you register manually a component after a "group" registration, an exception will be thrown, but not vice versa.
For example
//YourImplementation lives in assembly 'a'
IoC.Container.Register(
Component.For<YourInterface>().ImplementedBy<YourImplementation>().LifestyleSingleton()
);
IoC.Container.Register(
Classes.FromAssemblyNamed(a)
.Pick()
.WithService.FirstInterface()
.Configure(o => o.LifeStyle.PerWebRequest)
);

How can I moq this query against ravendb

I have this code in my project, how can I use Moq to moq the documentsession and setup the return value?
_session.Query<IPageModel, PageByUrl>()
.Customize(x => x.WaitForNonStaleResultsAsOfLastWrite())
.FirstOrDefault(x => x.Metadata.Url == virtualUrl);
This is what I have tried before I asked
var session = new Mock<IDocumentSession>();
var pageModel = new DummyModel();
session.Setup(x => x.Query<IPageModel, PageByUrl>()
.Customize(y => y.WaitForNonStaleResultsAsOfLastWrite())
.FirstOrDefault(y => y.Metadata.Url == path)).Returns(pageModel);
This throws an exception and I can't figure out how to change the moq
System.NotSupportedException : Expression references a method that does not belong to the mocked object: x => x.Query<IPageModel,PageByUrl>().Customize(y => y.WaitForNonStaleResultsAsOfLastWrite()).FirstOrDefault<IPageModel>(y => y.Metadata.Url == .path)
at Moq.Mock.<>c__DisplayClass1c`2.<Setup>b__1b()
at Moq.Mock.Setup(Mock mock, Expression`1 expression, Func`1 condition)
at Moq.Mock`1.Setup(Expression`1 expression)
at BrickPile.Tests.Web.Routing.PathResolverTests.Home_Page_With_Default_Action(String path) in PathResolverTests.cs: line 26
Instead of mocking the document session, have you thought about using the embeddabledocumentstore? It could run completely in memory and you have the full database as backend for your tests.
See also this blog post which describes some of the backgrounds: http://novuscraft.com/blog/ravendb-and-the-repository-pattern
This question inspired a blog post.
The short answer: Don't. You're coupling your application to RavenDB and violating the Interface Segregation Principle. Instead, write a custom interface that specifies precisely what services your class (the system under test) needs. Write a wrapper class that implements that and delegates to RavenDB. This might use the Repository Pattern, or it might be something simpler. Your interface should be simple to mock.
You need to mock whatever IDocumentSession.Query() returns as a separate mock so that you can then setup the customize call. I'm typing this on my phone so I can't easily give you an example.

Auto-wiring for Ninject

Some of the IOC containers have what's called auto-wiring based on conventions, for e.g., IProductRepository maps to ProductRepository without any manual wiring on your part.
Is there such a thing with Ninject?
// use Ninject.Extensions.Conventions for convention-based binding
kernel.Scan(scanner =>
{
// look for types in this assembly
scanner.FromCallingAssembly();
// make ISomeType bind to SomeType by default (remove the 'I'!)
scanner.BindWith<DefaultBindingGenerator>();
});
copied from #Pete Montgomery comment
Ninject comes with an extension for convention based configuration. But you still need to configure your convenions. See https://github.com/ninject/ninject.extensions.conventions The syntax has changed for 3.0.0 but has become much more powerful. The following would add bindings for all classes in your system. But normally you want several of these conventions for different kind of classes (e.g. services are singletons, ....)
kernel.Bind(
x => x.FromThisAssembly()
.SelectAllClasses()
.BindAllInterfaces());

EF 4.0 IsAttachedTo extension method and error An object with the same key already exists

I was getting an error
An object with the same key already exists in the ObjectStateManager.
The ObjectStateManager cannot track multiple objects with the same
key.
After i googled it i found IsAttachedTo extension method there:
Is is possible to check if an object is already attached to a data context in Entity Framework?
here is my code:
foreach (string s in types)
{
Subscription subscription = new Subscription { Id = Int32.Parse(s) };
if (service.repository._context.IsAttachedTo(subscription))
service.repository._context.Detach(subscription);
service.repository._context.AttachTo("Subscriptions", subscription); //error here
horse.Subscriptions.Add(subscription);
}
But when the subscription with the same key appeared in the foreach loop the extension method IsAttachedTo returning false every time, it is does not detect that there is already such entity attached. And in result i am getting the same error:
An object with the same key already exists in the ObjectStateManager.
The ObjectStateManager cannot track multiple objects with the same
key.
Why it is could be?
What can i do to fix that?
I have little code review for you because your sample code scares me.
You probably read a lot about fancy design patterns and layered architectures and you started to use them yourselves. Unfortunately you missed the main point. What the hell is this?
service.repository._context.XXX
Why do you bother with any service layer or repository layer if they don't encapsulate their logic? Why do you expose repository on the service? Nobody should know about service internal implementation? Even worse why do you expose context on the repository? That spoiled the whole point of the repository!
There are a lot of supporting rules for writing high quality object oriented code. One of this rules is called Law of Demeter. You don't have to follow each rule, you also don't have to follow rules all the time but in case of layered architecture this law is a must.
If you have three layers A -> B -> C the layer A can call methods on the layer B but it doesn't know about C and it cannot reach its methods. If it can, it is not a new layer but it is the same layer as B and the layer A doesn't need to call it through B, it can call it directly.
In your example you have just exposed D to A because A is current layer, B is service, C is repository and D is context.
One more points about your code. There are well known naming conventions. These conventions are not about I like this and you like that but about the fact that framework you are using follow these conventions strictly so using another one to mix your naming convention with framework naming convention make your code look messy.
I'm sorry, If this was only some example code to make your code structuring clear. I just needed to describe how wrong this code is.
Now to your real problem. The method you have referenced from the related question will not work in your case. I think it will work only if you load the subscription from the database. The reason is that the referenced method uses EntityKey (either internally or directly) to get the entity from context but your new entity doesn't have the entity key yet. I expect that calling TryGetObjectStateEntry for your entity will always return Detached. Entity key it is created during attaching or you have to build it manually.
If you want some IsAttachedTo method try this:
public bool IsAttachedTo<T>(this ObjectContext context, T entity) where T : IEntity
{
return context.GetObjectStateEntries(~EntityState.Detached)
.Where(e => !e.IsRelationship)
.Select(e => e.Entity)
.OfType<T>()
.Any(e => e.Id == entity.Id);
}
And make sure that your entity implements helper interface
public interface IEntity
{
int Id { get; }
}
But to be able to detach attached entity you will need:
public T GetAttached<T>(this ObjectContext context, T entity) where T : IEntity
{
return context.GetObjectStateEntries(~EntityState.Detached)
.Where(e => !e.IsRelationship)
.Select(e => e.Entity)
.OfType<T>()
.SingleOrDefault(e => e.Id == entity.Id);
}
You will have to detach instance returned from this method.
Anyway I would start to think why do you need that for the first place because it looks like your architecture has another wrong concept. Why don't you use attached entities directly? If you don't use them why do you even keep the context with them?
It's likely that IsAttachedTo does not compare by the key (Id) but by object identity. Because you create a new Subscription for every item in the loop the objects are all different instances.
Since you seem to have objects with same Id in your types collection but in the end only want to add one object per key into the context you can perhaps make your life easier by filtering out the duplicates in the first place:
var distinctTypes = types.Distinct();
foreach (string s in distinctTypes)
{
Subscription subscription = new Subscription { Id = Int32.Parse(s) };
service.repository._context.AttachTo("Subscriptions", subscription);
horse.Subscriptions.Add(subscription);
}
This way there should be only one object per key which gets attached to the context.