Custom database name for persisting host sagas - ravendb

Is it possible to use custom database name (not endpoint) for persisting nservicebus host sagas using ravenDb?
I use NServiceBus 3.3 and RavenDB 2.5. and initialize endpoind in such way:
public class RavenConfig : IWantCustomInitialization
{
public void Init()
{
Configure.Instance.RavenPersistence("AllHostsRavenDB");
Configure.Instance.RavenSagaPersister();
Configure.Instance.RavenSubscriptionStorage();
Configure.Instance.UseRavenTimeoutPersister();
}
}
My App.config contains:
<connectionStrings>
<add name="AllHostsRavenDB"
connectionString="Url=http://localhost:8080; DefaultDatabase=ABC;" />
</connectionStrings>

I finally got it working! I changed my custom intitialization from:
public class RavenConfig : IWantCustomInitialization
{
public void Init()
{
Configure.Instance.RavenPersistence("AllHostsRavenDB");
Configure.Instance.RavenSagaPersister();
Configure.Instance.RavenSubscriptionStorage();
Configure.Instance.UseRavenTimeoutPersister();
}
}
to:
public class RavenConfig : IWantToRunBeforeConfigurationIsFinalized
{
public void Run()
{
Configure.Instance.RavenPersistence("AllHostsRavenDB");
Configure.Instance.RavenSagaPersister();
Configure.Instance.RavenSubscriptionStorage();
Configure.Instance.UseRavenTimeoutPersister();
}
}

From the documentation:
To control the database name in code, instead of via the
configuration, use the Configure.RavenPersistence(string
connectionStringName, string databaseName) signature. This can be
useful in a multitenant scenario.
http://docs.particular.net/nservicebus/ravendb/#nservicebus-3-and-nservicebus-4-overriding-the-defaults
Would that solve your problem?

Related

Creating a database context using the database first approach with entityframework core.

I want to be able to create a database context with entityframework core in my webapi project using the database first approach.
When I create like this it works very well
public class TestingContext : DbContext
{
public TestingContext(DbContextOptions<TestingContext> options)
: base(options)
{
}
public TestingContext()
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Data Source=xxxxxx;Initial Catalog=xxxxxx;Integrated Security=False;User Id=xxxxx;Password=xxxxx;MultipleActiveResultSets=True");
}
public DbSet<Information> Information { get; set; }
public DbSet<ArticleUser> ArticleUser { get; set; }
}
I had to add the line services.AddDbContext to make it work.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddCors();
//using Dependency Injection
services.AddSingleton<Ixxx, xxx>();
// Add framework services.
services.AddApplicationInsightsTelemetry(Configuration);
services.AddDbContext<TestingContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
// Register the Swagger generator, defining one or more Swagger documents
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Title = "Articles API", Version = "v1" });
});
}
If I remove this method from my TestingContext
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Data Source=xxxxxx;Initial Catalog=xxxxxx;Integrated Security=False;User Id=xxxxx;Password=xxxxx;MultipleActiveResultSets=True");
}
I get the error below.
No database provider has been configured for this DbContext.
A provider can be configured by overriding the DbContext.OnConfiguring method or
by using AddDbContext on the application service provider. If AddDbContext is used,
then also ensure that your DbContext type accepts a DbContextOptions object in its
constructor and passes it to the base constructor for DbContext.
Why do I need to pass my connection string to the database in two places before it can pull my data. Please assist. I am new to the core. The two places are configure services method and the context itself.
Option 1: Remove parameterized constructor and OnConfiguring. Result:
public class TestingContext : DbContext
{
public DbSet<Information> Information { get; set; }
public DbSet<ArticleUser> ArticleUser { get; set; }
}
Option 2: Remove parameterized constructor and options in ConfigureServices in AddDbContext
Result:
In Startup.cs
services.AddDbContext<TestingContext>();
In TestingDbContext.cs
public class TestingDdContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Data Source=xxxxxx;Initial Catalog=xxxxxx;Integrated Security=False;User Id=xxxxx;Password=xxxxx;MultipleActiveResultSets=True");
}
public DbSet<Information> Information { get; set; }
public DbSet<ArticleUser> ArticleUser { get; set; }
}
Option 3: A parametric constructor is needed to create factory. Example:
public class TestDdContext : DbContext
{
public TestDdContext(DbContextOptions options) : base(options)
{
}
//TODO: DbSets
}
public class TestDbContextFactory : IDbContextFactory<TestDdContext>
{
public TestDdContext Create(DbContextFactoryOptions options)
{
var contextOptions = new DbContextOptionsBuilder();
contextOptions.UseSqlServer("...");
return new TestDdContext(contextOptions.Options);
}
}
If you are creating tests, do you need a backing Sql database? Would the In-memory provider not serve you better?
options.UseInMemoryDatabase("database-name");
For this reason, I'd ditch using the OnConfiguring method, and rely on passing the DbContextOptions to your constructor
Side note, you have to consider what you are testing - are you testing your code that is dependent on your DbContext, or are you testing your DbContext itself - if there is no custom logic and you are merely extending the DbContext, there may not be enough value in writing tests for it - and you're not responsible for testing EFCore itself.

Self-host (No IIS or WAS) WCF with a service that requires parameters

Hopefully this is an easy one. I'm wondering if this is possible - perhaps it is not. I'm attempting to self-host a WCF service (in my example below it is a console application). The service does not have a default constructor. It only contains a single parameter signature constructor. I need the service to be able to handle user sessions. Currently I am using Ninject DI. Here is a simple code solution I came up with to demonstrate my issue:
using System;
using System.ServiceModel;
using System.ServiceModel.Web;
using Ninject.Modules;
namespace ConsoleApplication1
{
public class Program
{
static void Main()
{
using (var webServiceHost = new WebServiceHost(typeof(MyWcf)))
{
var webHttpBinding = new WebHttpBinding();
var uri = new Uri("http://localhost:8000/");
webServiceHost.AddServiceEndpoint(typeof(IMyWcf), webHttpBinding, uri);
webServiceHost.Open();
Console.WriteLine("Service is ready...");
Console.ReadKey();
}
}
}
[ServiceContract]
public interface IMyWcf
{
[OperationContract, WebGet(UriTemplate = "")]
string HelloWorld();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class MyWcf : IMyWcf
{
private readonly IMessage _customMessage = new Message("Default Message.");
public MyWcf(IMessage message)
{
_customMessage = message;
}
public string HelloWorld()
{
return _customMessage.Text;
}
}
public interface IMessage
{
string Text { get; }
}
public class Message : IMessage
{
public Message (string message)
{
Text = message;
}
public string Text { get; set; }
}
public class NinjectSetup : NinjectModule
{
public override void Load()
{
Bind<IMessage>().To<Message>()
.WithConstructorArgument("message", "Injected String Message.");
}
}
}
Obviously commenting out the parameterized constructor allows the service to run. But that does me no good. I don't want to use ServiceHostFactory because that apparently requires me to have a .svc/IIS. Is there a way around this? Can I just create a new MyWebServiceHost that inherits from WebServiceHost and override some method that will create a instance for the service?
Using Ruben's suggestion (in the comments) above, I was able to locate a working example within the Ninject.Extensions.Wcf source repository.

Ninject with WCF and Interception (for AOP)

I've been trying to get the ninject working in wcf, using the wcf extension and the interception with dynamicproxy2 extension. I've basically created a Time attribute and have it all working in a basic scenario. Where I get trouble is when in ninject module I create my service binding with a constructor argument:
Bind<IMyDependency>().To<MyDependency>();
Bind<IService1>().To<Service1>().WithConstructorArgument("dependency", Kernel.Get<IMyDependency>());
Everything works fine, but the Time attribute wont fire on anything in my Service1 or MyDependency.
The time attribute is the standard one floating all over the internet. The only other piece of code really is the CreateKernel method is the global.asax, which looks like this:
protected override IKernel CreateKernel() {
IKernel kernel = new StandardKernel(
new NinjectSettings() { LoadExtensions = false },
new WcfNinjectModule(),
new DynamicProxy2Module()
);
return kernel;
}
Thanks for any help!
Matt
EDIT 12/12/2011: As requested, I've added some more detail below:
The entire wcf ninject module:
public class WcfNinjectModule : NinjectModule
{
public override void Load()
{
Bind<IMyDependency>().To<MyDependency>();
Bind<IService1>().To<Service1>();
}
}
The create kernel method in the global.asax is above, and the global.asax inherits from NinjectWcfApplication.
Service method looks like this:
public class Service1 : IService1
{
private IMyDependency _dependency;
public Service1()
{
}
public Service1(IMyDependency dependency)
{
_dependency = dependency;
}
[Time]
public virtual string GetData(string value)
{
return string.Format(_dependency.GetMyString(), value);
}
}
public interface IMyDependency
{
string GetMyString();
}
public class MyDependency : IMyDependency
{
[Time]
public virtual string GetMyString()
{
return "Hello {0}";
}
}
Does this help?
Since removing the 'WithConstructor' argument, the time intercept attribute will fire on GetMyString but not on GetData.
Matt
After a little more work (and writing that last post edit), it turns out that just removing the WithConstructorArgument method did resolve my problem and everything now seems to be working fine.
Matt

How to set up custom membership provider class to use repository?

Hey it's my first post so I'm ask for understanding. I've looked many posts but I didn't find solution.
I want to implement custom membershiprovider class with:
namespace Mvc_car.Authorization
{
public class SimpleMembershipProvider : MembershipProvider
{
private NHibernateRepository<Uzytkownik> repo;
ISession session;
[Inject]
public SimpleMembershipProvider(ISession session)
{
this.session = session;
}
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
{
repo = new NHibernateRepository<Uzytkownik>(session);
base.Initialize(name, config);
}
my bindings:
kernel.Bind<ISession>().ToMethod(x => MvcApplication.SessionFactory.OpenSession()).InRequestScope();
kernel.Bind(typeof(IRepository<>)).To(typeof(NHibernateRepository<>));
kernel.Inject(Membership.Provider); //either with or without that
I've changed in web.config:
<membership defaultProvider="MyMembershipProvider">
<providers>
<clear/>
<add name="MyMembershipProvider" type="Mvc_car.Authorization.SimpleMembershipProvider"/>
</providers>
</membership>
after try of logging following error occurs:
This method cannot be called during the application's pre-start initialization stage.
The solution to this is pretty simple. In your class containing the PreApplicationStartMethod attribute, add a static method like this.
public static class NinjectWebCommon
{
public static void InjectProviders()
{
Bootstrapper.Kernel.Inject(Membership.Provider);
Bootstrapper.Kernel.Inject(Roles.Provider);
}
...
}
When setting up your Provider, dont inject the dependencies through the constructor. Instead decorate the properties with an [Inject] attribute like this.
public class DefaultMembershipProvider : MembershipProvider
{
[Inject]
public IUserRepository UserRepository { get; set; }
}
After that, its as simple as calling NinjectWebCommon.InjectProviders() from your global.asax Application_Start() method.
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
NinjectWebCommon.InjectProviders();
...
}
}

Does StructureMap have scoping corresponding to NInject's DefinesNamedScope/InNamedScope?

The problem I'd like to solve is sharing an ISessionProvider between IXyzRepositories (where ISessionProvider holds the current NHibernate ISession).
I'm tweaking the "Setting up session per presenter" recipe from NHibernate 3 Cookbook, and would like to keep StructureMap (brownfield project).
I think you would have to create a custom Lifecyle to do that, although I am not sure what exactly you are trying to accomplish...
To create a custom Lifecycle, you just have to implement the ILifecycle interface and the use it in your registration. Here is an example you can look at: http://blog.mikeobrien.net/2010/01/creating-structuremap-lifecycle-for-wcf.html.
In a web application I use Singleton for the sessionFactory and HybridHttpOrThreadLocalScoped for the session:
This is my structuremap registry:
public class NhibernateRegistry: Registry
{
public NhibernateRegistry()
{
For<ISessionFactory>()
.Singleton()
.Use(new NHibernateSessionFactory(connectionString).SessionFactory);
For<ISession>()
.HybridHttpOrThreadLocalScoped()
.Use(o => o.GetInstance<ISessionFactory>().CurrentSession);
}
}
My NHibernateSessionFactory is similar to SessionProvider class used in the book.
Everything is disposed at the end of the request (web app):
protected void Application_EndRequest(object sender, EventArgs e)
{
ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
}
I use a generic repository:
public class GenericRepository<T> : IGenericRepository<T> where T : class
{
private readonly ISession _session;
public GenericRepository(ISession session)
{
_session = session;
}
public T Load(Guid Code)
{
return (_session.Load<T>(Code));
}
}
but you can easily change it with your own implementation.
I register the repository here:
public class RepositoriesRegistry : Registry
{
public RepositoriesRegistry()
{
For <Data.IRepository<Domain.Reminder, Guid>>()
.HybridHttpOrThreadLocalScoped()
.Use<Data.NH.Repository<Domain.Reminder, Guid>>();
}
}