How to set Connection String with Entity Framework - c#

I am using EF6 with MySQL and have a Model that I will use for MULTIPLE Databases.
I would like to be able to set the connections settings in my Form.
How do I set the Connection String for my Model programatically?

you should use EntityConnectionFactory
Here is what you need.
public string CreateConnectionString(string BasicConnectionString)
{
//EntityConnectionFactory
var entityConnectionStringBuilder= new EntityConnectionStringBuilder();
entityConnectionStringBuilder.Provider = "Your Provicer here" //For me it is "System.Data.SqlClient";
entityConnectionStringBuilder.ProviderConnectionString = BasicConnectionString;
entityConnectionStringBuilder.Metadata = "res://*";
return entityConnectionStringBuilder.ToString();
}
Here is an sample usage
MyContext ctx = new MyContext(CreateConnectionString())
:: Update ::
As you are using DB first method, see the following image
when these two radio buttons are available, select the first one. Then you will be able to set the connection string of your model.
Here is how my context looks like (Though it is object context. But doesn't matter in context of this question)
public partial class DataContext : ObjectContext
{
#region Constructors
/// <summary>
/// Initializes a new DataContext object using the connection string found in the 'DataContext' section of the application configuration file.
/// </summary>
public DataContext() : base("name=DataContext", "DataContext")
{
this.ContextOptions.LazyLoadingEnabled = true;
OnContextCreated();
}
/// <summary>
/// Initialize a new DataContext object.
/// </summary>
public DataContext(string connectionString) : base(connectionString, "DataContext")
{
this.ContextOptions.LazyLoadingEnabled = true;
OnContextCreated();
}
/// <summary>
/// Initialize a new DataContext object.
/// </summary>
public DataContext(EntityConnection connection) : base(connection, "DataContext")
{
this.ContextOptions.LazyLoadingEnabled = true;
OnContextCreated();
}
#endregion
#region Partial Methods
partial void OnContextCreated();
#endregion
...
}
Update
Add the constructor you are looking for in a partial class outside of the auto-generated entity class:
public partial class WMSChennaiDEVEntities : DbContext
{
public WMSChennaiDEVEntities(string connectionstring)
: base(connectionstring)
{
}
}
This constructor is not included in EF 5/6 apparently to prevent us from accidentally passing a sql connection string when an entity connection string is desired.

you have to hardcode the connection string somewhere. The common place is app.config.
<connectionStrings>
<add name="Connection1" connectionString="Server=localhost\ServerInstance;Database=MyDB;Trusted_Connection=True;" providerName="System.Data.SqlClient" />
Then in your Code First model, do the following:
public class MyContext : DbContext
{
public MyContext():base("Connection1")
{...}
You see that BCL db library and EF were all designed for such usage pattern.
Changing connection strings in UI is not desired in business applications since users won't change db location very often, unless you are developing a DB admin app or an installer.

Related

Make a connection Entity Framework dynamic

I have a connection string and I can do it without a problem
<connectionStrings>
<add name="DbName"
connectionString="server=serverName;database=DbTest;user=x;pwd=xxx;"
providerName="System.Data.SqlClient" />
</connectionStrings>
and I have the connection of Entity Framework:
public DbContext1() : base("DbName")
{
}
But I need to make a query to DbContext1 to get a new string connection from a table to connect to an other database, but I do not know how use the string connection that I receive from the query.
How can I use the string connection from the table to make a new DbContext?
Do something like this:
public DbContext1(string connString) : base(connString)
{
}
The constructor your derived class needs call is this one. The string argument is treated as either a valid connection string itself, or name of a connection string.
This sounds like a multi-tenant scenario where users authenticate against a central database then get directed to a specific database instance containing their own data. As a simple example during authentication:
using (var context = new AuthDbContext())
{ // Where AuthDbContext is the central DB containing authentication and the connection string to that user's home database..
// ... On successful authentication...
var connectionString = context.Tenants
.Where(x => x.TenantId == authenticatedUser.TenantId)
.Select(x => x.ConnectionString)
.Single();
}
Ideally if you are persisting user details (User ID, name, etc.) to session state then you could load the associated connection string and persist it as part of that data structure as well.
Then create a AppDbContextFactory class or UnitOfWork pattern class to inject into your services/controllers to provide a DbContext based on the current user's connection string.
As a very basic example:
public interface IUserStateFacade
{
string CurrentUserConnectionString { get; }
}
public class UserSessionState : IUserStateFacade
{
public const string UserStateSessionName = "UserState";
public string CurrentUserConnectionString
{
get
{
var userState = (UserSessionState)Session[UserStateSessionName] ?? throw new ApplicationException("Session state missing/expired.");
return userState.ConnectionString;
}
}
}
public interface IAppContextFactory
{
AppContext Create();
}
public class AppContextFactory
{
private readonly IUserStateFacade _userState = null;
public AppContextFactory(IUserStateFacade userState)
{
_userState = userState ?? throw new ArgumentNullException("userState");
}
/// <summary>
/// Create a DbContext. Calling code is responsible for disposing.
/// </summary>
public AppContext Create()
{
return new AppContext(_userState.ConnectionString);
}
}
Then in your controllers etc. that would normally want to create or inject a DbContext with a default constructor would instead use something like:
using (var context = AppContextFactory.Create())
{ }
or inject a value initialized via the AppContextFactory.
For ASP.Net apps using Session, you may need to wrap Session so that an dependency injection library can resolve the connection string/user structure out of the current session state.
Again, this is only a very rudimentary example to outline an option to facilitate dynamic connection strings assuming something like an ASP.Net web application. Additional security measures should be considered but it should hopefully provide some ideas on how it can be structured.

How to get current transaction in ASP.NET Boilerplate?

I have a project that written ASP.NET Boilerplate (assembly version=4.0.2.0).
I want get current transcation object in Application layer. How can I achieve this?
You get current unit of work with using IUnitOfWorkManager.
IUnitOfWorkManager _unitorWorkManager;
//...
[UnitOfWork]
public void Test(){
/*
Your code
*/
_unitOfWorkManager.Current//gives you current unit of work
.SaveChanges();//same thing with transaction.Commit();
}
If your class inherits something like AbpController, BackgroundJob, AbpServiceBase etc..., you can also use CurrentUnitOfWork.
//...
[UnitOfWork]
public void Test(){
/*
Your code
*/
CurrentUnitOfWork.SaveChanges();//same thing with transaction.Commit();
}
You can check https://aspnetboilerplate.com/Pages/Documents/Unit-Of-Work for more information.
Edit: I guess it is not possible to get it in application layer directly since it need dbcontext parameter. What about creating a domain service which provides ActiveDbTransaction. You can create an interface for that in *.Core project and define it where you can access to dbcontext
public interface IMyDbContextActiveTransactionProvider
{
/// <summary>
/// Gets the active transaction or null if current UOW is not transactional.
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
IDbTransaction GetActiveTransaction(ActiveTransactionProviderArgs args);
}
Implement it someplace you can access to dbcontext
public class MyDbContextActiveTransactionProvider: IMyDbContextActiveTransactionProvider, ITransientDependency {
private readonly IActiveTransactionProvider _transactionProvider;
public MyDbContextActiveTransactionProvider(IActiveTransactionProvider transactionProvider){
_transactionProvider = transactionProvider;
}
IDbTransaction GetActiveTransaction(ActiveTransactionProviderArgs args){
return _transactionProvider.GetActiveTransaction(new ActiveTransactionProviderArgs
{
{"ContextType", typeof(MyDbContext) },
{"MultiTenancySide", MultiTenancySide }
});
}
}
https://aspnetboilerplate.com/Pages/Documents/Articles/Using-Stored-Procedures,-User-Defined-Functions-and-Views/index.html#DocHelperMethods

Generic implementation to Avoid Lazy Loading in EF with multiple Database Context (using partial class)

In my project I do have many Database Contexts.
1. MyContext1
2. MyContext2
3. MyContext3
I am currently using database first approach (edmx based).
As part of edmx creation all these contexts are created. I would like to disable lazy loading for all these contexts.
I thought of writing a partial class for this. So for each Context there will be a partial class and which is responsible for disabling the lazy loading.
My current approach is something like below
[DbConfigurationType(typeof(InterceptorConfiguration))]
public partial class MyContext1 : DbContext
{
public static MyContext1 Create()
{
var applicationDbContext = new MyContext1();
applicationDbContext.Configuration.LazyLoadingEnabled = false;
return applicationDbContext;
}
}
Here i do have static method where i manually create instance of context and apply the configurations and returning it. Is there any other way to do this without creating a direct instance in the partial class?
Since there is already a default constructor in the edmx auto generated class I cannot write a constructor in the partial class which I have created.
I can disable this one in service layer, but since this one is an existing project I dont want to touch everywhere. So is there any better solution to do the same ?
Since this one is an existing application and it has many edmx files I cannot edit/change anything in the edmx including t4 template
Finally got a solution.
Since I am using Simple Injector Dependency Injection package in my solution.
I have created a provider for getting the instance at run time.
public sealed class DbContextProvider<T> : IDbContextProvider<T>
where T : DbContext
{
/// <summary>
/// The producer
/// </summary>
private readonly InstanceProducer producer;
/// <summary>
/// Initializes a new instance of the <see cref="DbContextProvider{T}"/> class.
/// </summary>
/// <param name="container">The container.</param>
/// <exception cref="InvalidOperationException">You forgot to register {typeof(T).Name}. Please call: " +
/// $"container.Register<{typeof(T).Name}>(Lifestyle.Scope);</exception>
public DbContextProvider(Container container)
{
this.producer = container.GetCurrentRegistrations()
.FirstOrDefault(r => r.ServiceType == typeof(T))
?? throw new InvalidOperationException(
$"You forgot to register {typeof(T).Name}. Please call: " +
$"container.Register<{typeof(T).Name}>(Lifestyle.Scope);");
}
/// <summary>
/// Gets the context.
/// </summary>
/// <value>
/// The context.
/// </value>
public T Context
{
get
{
DbContext dbContext = (T)this.producer.GetInstance();
//Dynamic proxies are used for change tracking and lazy loading
//if DbContext.Configuration.ProxyCreationEnabled is set to false, DbContext will not load child objects
//for some parent object unless Include method is called on parent object.
dbContext.Configuration.ProxyCreationEnabled = false;
return (T)dbContext;
}
}
}
Then the interface
public interface IDbContextProvider<out T> where T : DbContext
{
/// <summary>
/// Gets the context.
/// </summary>
/// <value>
/// The context.
/// </value>
T Context { get; }
}
I can call this one from service layer like
private readonly IDbContextProvider<MyDbContext> _baseContextProvider;
public MyService(IDbContextProvider<MyDbContext> baseContextProvider)
{
this._baseContextProvider = baseContextProvider;
}

Custom MembershipProvider: No parameterless constructor defined for this object

I have a custom MembershipProvider class that inherits from MembershipProvider that takes two parameters:
public class CustomMembershipProvider : MembershipProvider
{
private readonly ISecurityRepository _securityRepository;
private readonly IUserRepository _userRepository;
public CustomMembershipProvider(ISecurityRepository securityRepository, IUserRepository userRepository)
{
...
}
public override MembershipUser GetUser(string username, bool userIsOnline)
{
...
}
... etc
}
The config file for this looks similar to this:
<membership defaultProvider="CustomMembershipProvider">
<providers>
<clear />
<add name="CustomMembershipProvider" type="Library.Membership.CustomMembershipProvider" />
</providers>
</membership>
This works fine mostly throughout my web application for logging in and logging out. I am using Unity for DI and have the necessary classes setup in my Boostrapper.cs class.
However I recently ran into an issue when I wanted to create a custom User class and called the Membership.GetUser method. I get the following exception when I do:
{"No parameterless constructor defined for this object. (C:\\*app path*\\web.config line 43)"}
Line 43 in my config file points to the custom membership provider that I posted above. I think that elsewhere the app is using Unity to resolve those parameters but when using the Membership class it doesn't.
Is there any way I can tell the application how to resolve those dependencies or if not is there a way of adding those dependencies to my membership provider without using the concrete implementation?
EDIT 1:
Here is the custom User class:
public class User : MembershipUser
{
public int UserId { get; set; }
public string Username { get; set; }
public string Email { get; set; }
public DateTime LastLoggedOnDate { get; set; }
...
}
EDIT 2:
In my custom membership provider class this is what the GetUser method looks like:
public override MembershipUser GetUser(string username, bool userIsOnline)
{
return _userRepository.GetUser(username);
}
The problem is that you can't inject into the Membership provider via constructor. Refer to this question
I implemented a Custom Membership Provider using Ninject and I used the ServiceLocator to get the instance of the service.
public class AccountMembershipProvider : MembershipProvider
{
private readonly IUsers _users;
public AccountMembershipProvider()
{
_users = ServiceLocator.Current.GetInstance<IUsers>();
}
public override bool ValidateUser(string username, string password)
{
return _users.IsValidLogin(username, password);
}
...
}
In your case, you need to get the IUserRepository and ISecurityRepository.
When you wire your Interfaces/services
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUsers>().To<UsersService>();
kernel.Bind<IRoles>().To<RolesService>();
kernel.Bind<MembershipProvider>().To<AccountMembershipProvider>().InRequestScope();
kernel.Bind<RoleProvider>().To<AccountRoleProvider>().InRequestScope();
}
You can check a complete example of it working (using Ninject but you can adapt it to Unity) here: https://github.com/lopezbertoni/SampleApp
Hope this helps,
I also use Unity and implemented a custom membership provider, but used a slightly different approach. Check the code sample:
/// <summary>
/// Defines the custom membership provider class.
/// </summary>
public class SsoMembershipProvider : MembershipProvider
{
private IApplicationsRepository _appsRepo;
private IUsersRepository _usersRepo;
private IMembershipsRepository _membershipsRepo;
/// <summary>
/// Initializes a new instance of the <see cref="SsoMembershipProvider"/> class
/// using injectionConstructor attribute in order to get the repositories needed.
/// </summary>
/// <param name="appsRepo">The apps repo.</param>
/// <param name="usersRepo">The users repo.</param>
/// <param name="membershipsRepo">The memberships repo.</param>
[InjectionConstructor]
public SsoMembershipProvider(IApplicationsRepository appsRepo, IUsersRepository usersRepo, IMembershipsRepository membershipsRepo)
{
_appsRepo = appsRepo;
_usersRepo = usersRepo;
_membershipsRepo = membershipsRepo;
}
/// <summary>
/// Initializes a new instance of the <see cref="SsoMembershipProvider"/> class.
/// which calls the internal contructor.
/// </summary>
/// <remarks>This is happening due to the fact that membership provider needs a
/// parametless constructor to be initialized</remarks>
public SsoMembershipProvider()
: this(DependencyResolver.Current.GetService<IApplicationsRepository>(),
DependencyResolver.Current.GetService<IUsersRepository>(),
DependencyResolver.Current.GetService<IMembershipsRepository>())
{ }
}
This worked for me
public ICustomerRepository CustomerRepository {
get { return DependencyResolver.Current.GetService<ICustomerRepository>(); }
}
and then use
public override bool ValidateUser(string username, string password)
{
var abc = CustomerRepository.ValidateCustomer(username, password);
}

Entity Framework 4.1 - EFTracingProvider

Is there a way to make the EFTracing provider work with EF 4.1?
EFTracing seems to need an objectcontext and I use dbcontext.
Thanks in advance!
Yes, you can. I'm using the community version with both database-first DbContexts and code-first DbContexts. This answer is based on a discussion thread on the project site.
For database-first/designer DbContexts (via ADO.NET DbContext Generator templates), you can simply add the following constructor:
public abstract class MyDbContext : DbContext
{
protected MyDbContext(string nameOrConnectionString)
: base(EFTracingProviderUtils.CreateTracedEntityConnection(nameOrConnectionString), true)
{
// enable sql tracing
((IObjectContextAdapter) this).ObjectContext.EnableTracing();
}
}
For code first DbContexts its a bit more complicated since the EFTracingProvider wants a full entity connection string. You have to create an instance of EFTracingConnection manually. The following example will work for both database first and code first contexts.
public abstract class MyDbContext : DbContext
{
protected MyDbContext(string nameOrConnectionString)
: base(CreateTracingConnection(nameOrConnectionString), true)
{
// enable sql tracing
((IObjectContextAdapter) this).ObjectContext.EnableTracing();
}
private static DbConnection CreateTracingConnection(string nameOrConnectionString)
{
try
{
// this only supports entity connection strings http://msdn.microsoft.com/en-us/library/cc716756.aspx
return EFTracingProviderUtils.CreateTracedEntityConnection(nameOrConnectionString);
}
catch (ArgumentException)
{
// an invalid entity connection string is assumed to be a normal connection string name or connection string (Code First)
ConnectionStringSettings connectionStringSetting =
ConfigurationManager.ConnectionStrings[nameOrConnectionString];
string connectionString;
string providerName;
if (connectionStringSetting != null)
{
connectionString = connectionStringSetting.ConnectionString;
providerName = connectionStringSetting.ProviderName;
}
else
{
providerName = "System.Data.SqlClient";
connectionString = nameOrConnectionString;
}
return CreateTracingConnection(connectionString, providerName);
}
}
private static EFTracingConnection CreateTracingConnection(string connectionString, string providerInvariantName)
{
// based on the example at http://jkowalski.com/2010/04/23/logging-sql-statements-in-entity-frameworkcode-first/
string wrapperConnectionString =
String.Format(#"wrappedProvider={0};{1}", providerInvariantName, connectionString);
EFTracingConnection connection =
new EFTracingConnection
{
ConnectionString = wrapperConnectionString
};
return connection;
}
}
Whilst the previous answers work, I've found them problematic, a much simpler solution is to use the Clutch.Diagnostics.EntityFramework package from NuGet that uses MiniProfiler behind the scenes. It is significantly simpler to get working than EFTracingProvider, and a much more flexible solution.
The project is on GitHub at https://github.com/Kukkimonsuta/Clutch
For EFTracingProvider like functionality install the NuGet package and then implement IDbTracingListener like this:
using System;
using System.Data.Common;
using System.Diagnostics;
using Clutch.Diagnostics.EntityFramework;
/// <summary>
///
/// </summary>
public class DbTracingListener : IDbTracingListener
{
/// <summary>
///
/// </summary>
/// <param name="connection"></param>
/// <param name="command"></param>
/// <param name="result"></param>
/// <param name="duration"></param>
public void CommandExecuted(DbConnection connection, DbCommand command, object result, TimeSpan duration)
{
Debug.WriteLine(command.CommandText);
Debug.WriteLine(string.Format("Executed in: {0}", duration));
}
/// <summary>
///
/// </summary>
/// <param name="connection"></param>
/// <param name="command"></param>
public void CommandExecuting(DbConnection connection, DbCommand command)
{
}
/// <summary>
///
/// </summary>
/// <param name="connection"></param>
/// <param name="command"></param>
/// <param name="exception"></param>
/// <param name="duration"></param>
public void CommandFailed(DbConnection connection, DbCommand command, Exception exception, TimeSpan duration)
{
}
/// <summary>
///
/// </summary>
/// <param name="connection"></param>
/// <param name="command"></param>
/// <param name="result"></param>
/// <param name="duration"></param>
public void CommandFinished(DbConnection connection, DbCommand command, object result, TimeSpan duration)
{
}
}
If you are using DBContext and MVC Model First, meaning using EntityConnections then the following sample code should be all you need:
public partial class BrickHouseFitnessContext : DbContext
{
public BrickHouseFitnessContext(): base(EntityConnectionWrapperUtils.CreateEntityConnectionWithWrappers(ConfigurationManager.ConnectionStrings["BrickHouseFitnessContext"].ConnectionString, "EFTracingProvider"), true)
{
}
Also:
In the Web.Config file add the following sections:
<system.data>
<DbProviderFactories>
<add name="EF Tracing Data Provider" invariant="EFTracingProvider" description="Tracing Provider Wrapper" type="EFTracingProvider.EFTracingProviderFactory, EFTracingProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=def642f226e0e59b" />
<add name="EF Generic Provider Wrapper" invariant="EFProviderWrapper" description="Generic Provider Wrapper" type="EFProviderWrapperToolkit.EFProviderWrapperFactory, EFProviderWrapperToolkit, Version=1.0.0.0, Culture=neutral, PublicKeyToken=def642f226e0e59b" />
</DbProviderFactories>
and:
<add key="EFTracingProvider.logToConsole" value="true" />
<add key="EFTracingProvider.logToFile" value="C:\BrickHouseFitnessSqlLog.txt" />
There is no need to include the ExtendedEntities or the other ObjectContext derived class mentioned in the original article. Run that code and you should see your log file as specified, with all the SQL commands in it. I am bypassing database intialization when tracing is enabled,

Categories

Resources