How do I use multiple databases with sqlmembershipprovider at runtime? - c#

I have a web application and two sql databases. My client wants different languages and I have solved it with resource files one the public parts of the site, no probs. The thing is they have two databases with the same structure and type of data but in different languages, and the users differs aswell. I have overrided "Initialize" from SqlMembershipProvider as:
public class MyqlMembershipProvider : SqlMembershipProvider
{
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
{
var connectionString = GetConnectionStringFromSelectedLanguage();
config["connectionStringName"] = connectionString;
base.Initialize(name, config);
}
}
But the Initialize gets invoked only once, I need to set the connectionString everytime I use Membership.yadayada depending on the language selected. I dont want to use Membership.Providers["one_provider"].DeleteUser(a_username) because It is used EVERYWHERE. How should I go about this, is there anything else I can override?
/Mike

This isn't possible. The membership provider is a static object initialized once and shared between users. Changing any of the values for it changes them for all users of the application. See this answer for a more thorough explanation...
How do I use multiple databases with sqlmembershipprovider at runtime?

You could use a DependencyInjection framework like Ninject for the application and build your repositories based on a named dependency.
For example, you could have an Interface which just provides the connection string name:
Interface IConnectionProvider
{
ConnectionName { get;}
}
class LanguageAProvider : IConnectionProvider
{
public string ConnectionName { get { return "dbnameLangA"; } }
}
class LanguageBProvider : IConnectionProvider
{
public string ConnectionName { get { return "dbnameLangB"; } }
}
public class MyqlMembershipProvider : SqlMembershipProvider
{
private readonly string _connectionStringName;
public MyqlMembershipProvider (IConnectionProvider connection)
{
_connectionStringName = connection.ConnectionName;
}
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
{
var connectionString = GetConnectionStringFromSelectedLanguage();
config[_connectionStringName] = _connectionStringName;//I'm not sure how you need to use the connection name here.
base.Initialize(name, config);
}
}
I haven't tested any of this, but it could be an idea. You could then have Named Bindings to select the required dependency at run time.

I need to set the connectionString everytime I use Membership.yadayada depending on the language selected
This isn't feasible: consider what happens when two requests from users with different languages are processed concurrently. If you changed the connection string for user A, it would affect user B.
What you could do is write a custom Membership provider which aggregates two (or more) SqlMembershipProviders, and redirects based on the current user's language.
public class MyMembershipProvider : MembershipProvider
{
private Dictionary<string, MembershipProvider> _languageMembeshipProviders;
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
{
... create an SqlMembershipProvider for each language and add to
... the languageMembeshipProviders dictionary
}
public override bool ValidateUser(...)
{
... Get language from HttpContext.Current somehow
... select a provider from the dictionary
... call the provider
}
}
However I find it difficult to understand how this could work in practice. Presumably there's something in the request (querystring, cookie, accept-languages header) to indicate the user's language. If so, a user could potentially be authenticated using one language, then switch to access the other database by changing the language in his request.
I'd have thought it would be simpler and cleaner to have separate applications for each language. If a user arrives on site A indicating he wants language B, then he should be redirected to the application B.

Related

Domain model validation, inheritance and testability

The Situation
I'm building a C# web application and I want to model my app configuration as an explicit dependency to be handed in through the constructor of a service instead of relying on System.Configuration.ConfigurationManager directly in each of the classes. This did bite my quite often in the past so I want the dependency to be explicit so that the next maintainer of the project (probably future me) doesn't have to guess where my services get their configuration settings - on top of that it is more TDD friendly. Furthermore I'm currently reading Eric Evan's Domain Driven Design and I really want to embrace his DDD approach.
I started modeling the configuration class and corresponding value objects to avoid Primitive Obsession but I hit some bumps on the way and I'm not sure how to handle them appropriately. Here is my current approach:
// Role interface that can be requested via constructor injection
interface IAppConnectionStringsConfig
{
OleDbConnectionString AuthenticationConnectionString { get; }
}
// A base class for handling common functionality like
// parsing comma separated lists or default values
class abstract AppConfigBase
{
protected string GetStringAppSetting(string key)
{
// Get the appropriate string or a default value from
// System.Configuration.ConfigurationManager
return theSettingFromSomeConfigSource;
}
}
// A value object for OLEDB connection strings that also has a
// convenient implicit conversion to string
class OleDbConnectionString
{
public readonly string Value;
public OleDbConnectionString(string connectionString)
{
Contract.Requires(connectionString != null);
this.VerifyStructure(connectionString);
this.Value = connectionString;
}
private void VerifyStructure(string text)
{
Contract.Requires(text != null);
// Verify that the given string fulfills the special
// needs of an OleDbConnectionString (including Provider=...)
if (!/* isValidOleDbConnectionString */)
{
throw new FormatException();
}
}
public implicit operator string(ConnectionString conn)
{
return conn.Value;
}
}
// The actual app config that implements our role interface
class AppConfig : AppConfigBase, IAppConnectionStringsConfig
{
public OleDbConnectionString AuthenticationConnectionString
{
get
{
return new OleDbConnectionString(this.GetStringAppSetting("authconn"));
}
}
}
The Problem
I know that constructor logic should be minimal and that is not a good idea to call virtual methods from the constructor. My questions are as follows:
1) Where should I put the validation logic for the OleDbConnectionString? I really want to prevent the creation of value objects in an invalid state - that's excrutiatingly usefull at a day to day basis :-)
I have the feeling that this is domain logic that should be owned by the class itself but on the other hand the constructor should do as little as possible - wouldn't the string parsing be too much or is this ok?
I could create a validator but I most certainly had to hand that in through the constructor for being able to test that thing properly and then I have to wire that manually or use a factory (I'm definitely not using a Service Locator). On top of that the validation now would be hidden in a separate service; I wouldn't have the temporal coupling since the constructor requires the validator but still that doesn't look right.
2) I wonder if it would be appropriate to make DDD value objects structs? They - like the name suggests - represent a single value and this value is immutable. But they would contain business logic in the form of validation
3) Is it OK to use a property for retrieving the connection string? It could throw an exception if the format for the string isn't valid. Furthermore it's perfectly possible that the implementation will be changed from reading from an xml config file to querying a database.
4) Any other comments on the design are welcome!
As a side note, I'm already using Code Contracts and there is a way to specify object invariants but I don't know whether this is really a good idea since these contracts are opt-in and in the case that they are inactive the invariants are no longer actively protected. I'm not sure about this, for development purposes to catch errors early it might be fine but for production it seems off.
Thx!
I never really thought about general settings as a DDD problem - are you modelling a domain that is about settings and how they are saved, or just allowing settings to be saved and used in an application that has some inner parts modeled as DDD?
You can split this out by separating concerns of getting settings away from the things that use the settings.
Is it OK to use a property for retrieving the connection string? It could throw an exception if the format for the string isn't valid.
I don't think its a good idea to throw an exception if a setting cannot be retrieved so you can return defaults which would allow the program to continue.
But also remember that the default returned value (i.e. a password, or network address) will probably cause the thing that depends on that setting to throw an exception.
I would look at allowing the construction to happen OK but when coming to use the service i.e. Sender.Send() or Sender.Connect() is when you would throw an exception.
Where should I put the validation logic for the OleDbConnectionString? I really want to prevent the creation of value objects in an invalid state
I create objects that can never return an invalid result, but they do return a default settings value:
public class ApplicationSettings : IIdentityAppSettings, IEventStoreSettings
{
/* snip */
static readonly object KeyLock = new object();
public byte[] StsSigningKey
{
get
{
byte[] key = null;
lock (KeyLock)
{
var configManager = WebConfigurationManager.OpenWebConfiguration("/");
var configElement = configManager.AppSettings.Settings["StsSigningKey"];
if (configElement == null)
{
key = CryptoRandom.CreateRandomKey(32);
configManager.AppSettings.Settings.Add("StsSigningKey", Convert.ToBase64String(key));
configManager.Save(ConfigurationSaveMode.Modified); // save to config file
}
else
{
key = Convert.FromBase64String(configElement.Value);
}
}
return key;
}
/* snip */
}
}
What I generally do
I have the settings interfaces for each bounded context defined in the domain model as part of the infrastructure - this allows a number of known interfaces which I can reference and trust to provide some form of settings.
ApplicationSettings is defined in the code that hosts my bounded context(s) be it a Console app or WebAPI or MVC etc, I may have multiple bounded contexts hosted under the same process, or may split them out as separate processes, either way it is the job of the hosting application to provide the relevant application settings and wiring can be done via the IoC container.
public class ApplicationSettings : IIdentityAppSettings, IEventStoreSettings
{
// implement interfaces here
}
public interface IEventStoreSettings
{
string EventStoreUsername { get; }
string EventStorePassword { get; }
string EventStoreAddress { get; }
int EventStorePort { get; }
}
public interface IIdentityAppSettings
{
byte[] StsSigningKey { get; }
}
I use SimpleInjector .NET IoC container to wire up my applications. I then register all the application interfaces with SimpleInjector (so i can query based on any of the application interfaces and have the settings class object returned):
resolver.RegisterAsImplementedInterfaces<ApplicationSettings>();
I can then have the specific interface injected in, an example is a command handler that uses an IRepository, which in turn the EventStoreRepository (which is wired up as an implementation of IRepository) uses IEventStoreSettings (which is wired up as the ApplicationSettings instance):
public class HandleUserStats : ICommandHandler<UserStats>
{
protected IRepository repository;
public HandleUserStats(IRepository repository)
{
this.repository = repository;
}
public void Handle(UserStats stats)
{
// do something
}
}
And my repository would in turn be wired up:
public class EventStoreRepository : IRepository
{
IEventStoreSettings eventStoreSettings;
public EventStoreRepository(IEventStoreSettings eventStoreSettings)
{
this.eventStoreSettings = eventStoreSettings;
}
public void Write(object obj)
{
// just some mockup code to show how to access setting
var eventStoreClient = new EventStoreClient(
this.eventStoreSettings.EventStoreUsername,
this.eventStoreSettings.EventStorePassword,
this.eventStoreSettings.EventStoreAddress,
this.eventStoreSettings.Port
);
// if ever there was an exception either during setup of the connection, or
// exception (if you don't return a default value) accessing settings, it
// could be caught and bubbled up as an InfrastructureException
// now do something with the event store! ....
}
}
I allow settings to be passed in from some external source (like a WCF receive, or MVC controller action) and wired up by getting resolver.GetInstance<CommandHandler<UserStats>>(); which wires up all the settings for me all the way down to the implementation level.

How to set connection string to DbContext after user has login with Unity container?

I am building an MVC application that connect to diferent databases depending on the user that has log in.
For this i have 3 projects DAL using entity framework(DataBaseFirst) where i have extended the dbcontext so that i can pass the connectionstring like this:
public partial class ARACultivoEntities
{
public ARACultivoEntities(string nameOfConnectionString)
: base(nameOfConnectionString)
{
}
}
Note: I have the connections strings defined in the web.config of the mvc project.
There is also another project, Services where i have a genericService from where other service can inherit this like this:
public class GenericService<T> : IGenericService<T>
where T : class
{
protected ARACultivoEntities Db;
protected DbSet<T> Table;
public GenericService(string nameConnectionString)
{
if (string.IsNullOrEmpty(nameConnectionString))
{
throw new ArgumentNullException("nameConnectionString");
}
Db = new ARACultivoEntities(nameConnectionString);
Table = Db.Set<T>();
}
Now i save the name of the connection string in the user claims when he logs in and in the controllers i have something like this:
public class DeduccionController : Controller
{
private IGenericService<Deducciones> service;
public DeduccionController()
{
service = ServiceFactoryGeneric<Deducciones>.InitGenericService(GetClaimsUser.Cadena);
//GetClaimsUser.Cadena has the name of the connectionString
//ServiceFactoryGeneric<Deducciones>.InitGenericService do this:
// return new GenericService<T>(connectionString);
}
now i want to instead of having my own factories i want to use an Ioc Container and i have chosen unity for this, i am new to this, i've read some articles and i think i undsertand the basics but i dont know how to pass the connection string after the user has log in because my RegisterTypes hapen at the application start
public static void RegisterTypes(IUnityContainer container)
{
// this happen at application start
// string nameOfConnectionString = *user is still not loged in*
container.RegisterType<IGenericService<T>, GenericService<T>>(
new InjectionConstructor(nameOfConnectionString));
}
i been thinkin to try to tweet the code to register my types after the user has loged in but i dont think this a good idea..
i also have been thinking about adding a public method to my IGenericService so that i can set my connectionString after the service is constructed and implemented something like this:
public void SetConnectionString(string nameOfConnectionString)
{
Db.Database.Connection.ConnectionString = nameOfConnectionString;
//not sure if this actually works
}
then my controller will be something like this:
public class DeduccionController : Controller
{
private IGenericService<Deducciones> _service;
public DeduccionController(IGenericService<Deducciones> service)
{
_service = service;
_service.SetConnectionString(GetUserClaims.Cadena);
}
and let my RegisterTypes just with the:
container.RegisterType<IGenericService<T>, GenericService<T>>()
but since i new to this world of IoCs i am not sure if this is the best way
What would be the correct way to do this using Unity?
Thank you for reading.
I am sorry for my english not my first languague.
I recently had to do something similar by swapping connection strings based on a route parameter specifying a geo-location.
I would recommend building your own Unity LifetimeManager that acts in a instance per session scope. Register an object that acts as a configuration container for the connection string property.
[See Unity Lifetime Manager: http://msdn.microsoft.com/en-us/library/microsoft.practices.unity.lifetimemanager(v=pandp.30).aspx]
Then you could inject that singleton instance of this configuration object into your controller and set the connection string property once a user has logged in. You could then inject that same singleton instance into a DbContext factory that instantiates your DbContext using the connection string specified in your configuration object.
Like I said, it may not be the most elegant solution, but I liked it better than having to pass a connection string through the many tiers of your application stack. Hope this helps.

Static Provider Dictionary Design

I'm rethinking a current WCF service we're using right now. We do A LOT of loading XML to various databases. In some cases, we can store it as XML data, and in others, we need to store it as rowsets.
So I'm redesigning this service to accept different providers. My first thought, classic abstract factory, but now I'm having my doubts. Essentially, the service class has one operation contract method, Load. But to me, it seems silly to new-up provider instances every time Load is called.
Currently:
// Obviously incomplete example:
public class XmlLoaderService : IXmlLoaderService
{
readonly IXmlLoaderFactory _xmlLoaderFactory;
readonly IXmlLoader _xmlLoader;
public XmlLoaderService()
{
_xmlLoader = _xmlLoaderFactory(ProviderConfiguration configuration);
}
public void Load(Request request)
{
_xmlLoader.Load(request);
}
}
I'm thinking about changing to:
public class XmlLoaderService : IXmlLoaderService
{
static readonly IDictionary<int, IXmlLoader> _providerDictionary;
static public XmlLoaderService()
{
_providerDictionary = PopulateDictionaryFromConfig();
}
public void Load(Request request)
{
// Request will always supply an int that identifies the
// request type, can be used as key in provider dictionary
var xmlLoader = _providerDictionary[request.RequestType];
xmlLoader.Load(request);
}
}
Is this a good approach? I like the idea of caching the providers, seems more efficient to me... though, I tend to overlook the obvious sometimes. Let me know your thoughts!
Why can't you use both? Pass in your dependency into the Load method and if the type is already cached use the cached instance.
public void Load(Request request)
{
// Request will always supply an int that identifies the
// request type, can be used as key in provider dictionary
IXmlLoader xmlLoader;
if(_providerDictionary.ContainsKey(request.RequestType))
{
xmlLoader = _providerDictionary[request.RequestType];
}
else
{
xmlLoader = //acquire from factory
_providerDictionary.Add(request.RequestType, xmlLoader);
}
xmlLoader.Load(request);
}

How to create a connection string manager to detect if server is available, return cache connection string if not

I have a occasionally connected application where there is a server that stores information about products. I am using a database cache to store this information locally so when a connection is unavailable the application will still work when trying to read the database.
Since the database is configured and I do not have access to modify the tables, I did not implement 2 way updating and it only downloads a snapshot. A side question is if it is possible to create a database cache and have 2-way sync with only tracking columns on the client machine? I cannot add any columns or tables to the server. I know this might be a question for a separate post, but if this is true then it would change my direction for this problem completely, to a separate module detecting and syncing the database and handling any sync errors that are thrown and always connecting to the cache.
I am using a generic repository and I am wondering what the best practice to go about handling if a connection is available or not and using either a local or remote database depending on this status.
Should I add an interface to the generic repository that handles returning the correct string, and lets the repository know if it is live or not? I need to enable/disable certain features depending on the connection state so I also will need a property somewhere so that when this repository is used there can be a way to bind various controls enabled state to this status.
Instead should I have a wrapper that contains for example an IRepository and IConnectionStringManager and then handles feeding and initializing the repository connection string based on availability? This wrapper would expose the repository and any status properties required.
I guess I am not sure if I should be setting up my program to use IRepository with all the automatic connection sensing behind the scenes, or if I should have IRepositoryManager that has a IRepository and IConnectionStringManager in it.
Maybe both of those options are wrong?
I like the way Entity Framework allows you to provide a connection string as a constructor argument to its contexts. That way you can leverage a dependency injection framework to apply special logic when creating the context, and you only have to change the code in one place (assuming you're using DI principles). You could do something similar with your repository implementation.
Update
Since you're using Entity Framework, here's an idea of what it might look like in code:
// DI Bindings, Ninject style
Bind<Func<MyContext>>().ToMethod(
c => new MyContext(
c.Kernel.Get<IConnectionManager>().IsOnline()
? OnlineConnectionString
: OfflineConnectionString));
// Usage
public class ThingRepository : IThingRepository
{
private Func<MyContext> _getContext;
public ThingRepository(Func<MyContext> getContext)
{
_getContext = getContext;
}
public IEnumerable<Thing> GetAllThings()
{
using(var context = _getContext())
{
return context.Things.ToList();
}
}
}
Or, if you prefer to use a more explicit factory implementation:
public interface IMyContextFactory
{
MyContextFactory Get();
}
public class MyContextFactory : IMyContextFactory
{
private const string OnlineConnectionString = "...";
private const string OfflineConnectionString = "...";
private IConnectionManager _connectionManager;
public MyContextFactory(IConnectionManager connectionManager)
{
_connectionManager = connectionManager;
}
public MyContextFactory Get()
{
var connectionString = _connectionManager.IsOnline()
? OnlineConnectionString
: OfflineConnectionString
return new MyContext(connectionString);
}
}
// DI Bindings, Ninject style
Bind<IMyContextFactory>().To<MyContextFactory>();
// Usage
public class ThingRepository : IThingRepository
{
private IMyContextFactory _myContextFactory;
public ThingRepository(IMyContextFactory myContextFactory)
{
_myContextFactory = myContextFactory;
}
public IEnumerable<Thing> GetAllThings()
{
using(var context = _myContextFactory.Get())
{
return context.Things.ToList();
}
}
}

Make available a variable in multiple forms in compact framework

I'm doing an application for a Windows CE 5.0 device that asks for the username in the first form (when the application is launched), and then I get the userId from a database table.
After that a menu form appears which receives the userId, and I have to send to each constructor of the menu options the userId in order to use it in those forms. I assume there must be a better way to do something like this.
Example:
public partial class Menu : Form
{
int userId;
public Menu(int userId)
{
InitializeComponent();
this.userId = userId;
}
private void buttonDelivery_Click(object sender, EventArgs e)
{
Delivery delivery = new Delivery(userId);
delivery.Show();
this.Hide();
}
...
May be I should use a global variable like this?
public static class UserConfiguration
{
public static int userId;
}
Isn't that also bad practice?
Finally bear in mind that compact framework doesn't support app.config files
Personally I'd vote for "neither", but would instead use some other architectural tools available.
I'd be highly inclined to have a class that incorporates all user info (the ID you're using and then maybe anything else, like name, etc). I'd create an instance and populate that info when the first Form (login) is submitted and I'd keep it in a DI container (I use this one specifically, but any CF-supporting container would work).
I'd then either use injection to either automatically push that instance into any class that needs it, or have the consumer pull it from the container as needed. Which mechanism I use would depend on which container I'm using and exactly how/when I need the info.
Since the data you're after is coming from a database, I'd actually be inclined to use an ORM (I use this one) to pull the data, which would give you the entity instance containing the user info you're after automatically anyway.
in my opinion both ways are good, in some cases some controls do not work properly if you change the constructor signature or in some cases your constructor would not be called if the framework always calls the one with no parameters. But really depends on the specific case.
I like more the method parameters way to pass the values, but the external class with static field would also work fine.
P.S. app.config is not the best place anyway to store runtime specific values so doesn't matter if supported or not by CF in this case ;-)
If you use a controller it can hold all the variables needed. The controller can have a static Instance property that instantiates itself (see Singleton object design pattern). When developing Mobile applications this is very common as memory is often a constraint. The rest of the methods are public members (not static) so you would access like this. You can either make them properties or just use the public member. Even with mobile we tend to not use properties as it just adds unecessary fluff and boxing/unboxing.
In one form you can use:
MainController.Instance.loginID = "me123";
on another you can use
MessageBox.Show("my loginID is: " + MainController.Instance.loginID);
You can also add methods like:
MainController.Instance.ClearSession();
Which internally just sets loginID to null. etc. Personally I use the main controller to show windows as well. Because in mobile we need to make sure our resources are cleaned up as well.
MainController.Instance.ShowLoginForm();
the MainController code as a start should look something like this:
public class MainController : IDisposable {
//all forms we are controlling
LoginForm _loginForm = null;
//all public members
public string loginID = null;
#region Singleton Instance stuff
private static MainController me = null;
private void MainController() { }
public static Instance {
get {
if(me == null) {
me = new MainController();
}
return me;
}
}
#endregion
//all public methods
public void Init(someargshere) {
//TODO some init like load config files, etc.
}
public void Dispose() {
//TODO cleanup
}
public void ClearSession() {
loginID = "";
}
public void ShowLoginForm() {
if(loginForm!=null) {
loginForm.Dispose();
loginForm == null;
}
loginForm = new LoginForm();
loginForm.Show();
loginForm.BringToFront();
}
//etc
}
So the very first thing you do in the Program.cs code is init your main controller
main(string[] args) {
//start a controller
MainController.Instance.Init(passomeargs if needed);
//now fire off our main form
Application.Run(new MainForm());
}
Now all forms there after can access it's data through the MainController
Personally I use commands and have the main controller hide and show forms based on the commands passed in so there is as little logic in the forms as possible. This may or may not lend well to what you are doing.
Good luck

Categories

Resources