I have created a project call Repository.EF to handle Data access in a n-tire solution. I have added EF to the Repository.EF project where I have all my POCO's . Then I created a DbContext class in that project like this.
namespace LearningSpike.Repositories.EF
{
class GlassContractDbContext:DbContext
{
public GlassContractDbContext() : base("GlassContractContext")
{
}
public DbSet<MetalStock> MetalStock { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new MetalStockConfiguration());
}
}
Then went to package manager console and did
Enable-Migrations
Then set the
AutomaticMigrationsEnabled = true;
Then
Update-Database
Everything is working fine. But the problem is, I don't know where the connection string is. It seems like there is no connectionString in that particular project. I know if I had an MVC4/5 template, there will be a connectionString in the web.config. How can I find the connection string?
How do I configure things now? For example I remember doing this with the connectionString in a MVC5 app
MultipleActiveResultSets=true
How do I do it now?
Thanks!
Cheers!
PS
Also I have the following code in my App.config in the Repository.EF Project
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="entityFramework"
type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection,
EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
requirePermission="false" />
<!-- For more information on Entity Framework configuration, visit
http://go.microsoft.com/fwlink/?LinkID=237468 --></configSections>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory,
EntityFramework" />
<providers>
<provider invariantName="System.Data.SqlClient"
type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
When running the package manager console it will default to use the start-up project (unless you specify the -project param in the command or use the drop down in console manager). From there it will look for your connection strings in the config files of that project. If that is a web project this will be in the web.config.
If you have not added your own connection string to that project, EF will be able to use its own one derived from the project name and create an mdf file which it attaches on the fly during runtime.
If you want to add a connection string (you can do this is any of your config files - however by the sounds of it you want to add this to the app.config in your datalayer project) you can add this below your config sections:
<connectionStrings>
<add name="MyDatabase"
providerName="System.Data.SqlClient"
connectionString="Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;"/>
</connectionStrings>
Related
I'm using the Model First approach with EF6 and I'm trying to use Entity Framework Effort to develop in-memory tests.
Here is what I do in my test:
var inMemoryConnection = Effort.DbConnectionFactory.CreateTransient("name=MyEntities");
var inMemoryContext = new MyEntities(inMemoryConnection);
MyEntities:
public partial class MyEntities: DbContext
{
public MyEntities(DbConnection dbConnection)
: base(dbConnection, contextOwnsConnection: true)
{
}
When I run the tests, I get an error saying I didn't specify any [key] attributes which is normal since I am not using a Code First approach. Therefor, the OnModelCreating method is called and shouldn't have to.
Is there a way to use Effort in a Model First design without having to add these attributes?
Thanks !
I found my mistake.
Turns out Effort.DbConnectionFactory.CreateTransient is used for Code-First.
Instead if you're working with a .edmx, Model-First, it is Effort.EntityConnectionFactory.CreateTransient("name=MyEntities") you have to use.
I too had a bit of a difficult time in trying to get Effort to work with a DB first, or model first as it's also known, approach. This is what I did to make it work:
Download the Effort.EF6 nuget package
Add the effort.provider to the entity-framework config section:
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
<provider invariantName="Effort.Provider" type="Effort.Provider.EffortProviderServices,Effort" />
</providers>
</entityFramework>
Replace the sql-provider with the Effort-provider in the connection-string:
<connectionStrings>
<add name="testDb" providerName="Effort.Provider" connectionString="metadata=res://*/StaginDB.csdl|res://*/StaginDB.ssdl|res://*/StaginDB.msl;provider=System.Data.SqlClient;provider connection string="data source=testDB;initial catalog=foobaroo;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" />
</connectionStrings>
If your model-first context doesn't offer a constructor you can inject a connection into, you can modify your tt-template to do so:
<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
{
// I added this constructor so I could inject a db-connection into the context:
public <#=code.Escape(container)#>(System.Data.Common.DbConnection dbConnection, bool contextOwnsConnection)
: base(dbConnection, contextOwnsConnection)
{
}
// Original constructor
public <#=code.Escape(container)#>()
: base("name=<#=container.Name#>")
{
<#
if (!loader.IsLazyLoadingEnabled(container))
{
#>
this.Configuration.LazyLoa.... etc. etc.
And we can now use that constructor to instantiate a connection, and an Effort-based in-memory db-context based on this connection:
System.Data.Common.DbConnection connection = Effort.EntityConnectionFactory.CreateTransient("name=KPDBSTAGINGEntities");
TestDbContext testDbContext = new testDbContext(connection, false);
TestDbContext.your-entity.add( new your-entity() { etc. tec. });
TestDbContext.SaveChanges();
Hope this helps.
P.S. Others have had to add a db-provider-factory section to their config. This was not required for me, but maybe for you:
<system.data>
<DbProviderFactories>
<add name="Effort.Provider" invariant="Effort.Provider" description="Effort.Provider" type="Effort.Provider.EffortProviderFactory,Effort" />
</DbProviderFactories>
</system.data>
I had migrations enabled - however, now I'm moving to the live server, it appears migrations are still trying to update the database, as I get the error:
CREATE TABLE permission denied in database 'secn'.
I have this in a context file in my models folder:
namespace lhts2.Models
{
public class DefaultConnection : DbContext
{
public DefaultConnection() : base("name=DefaultConnection")
{
Database.SetInitializer<DefaultConnection>(null);
}
}
}
...and in my web.config file, my connection string is:
<add name="DefaultConnection" connectionString="Data Source=[servername];
Initial Catalog=secn; Integrated Security=True;" providerName="System.Data.SqlClient" />
I have deleted the Migrations folder too, and republished - but still I get the error above.
I also have this in my web.config file:
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
Do I need to set the SetInitializer in some other place, other than in the context file in my models folder?
Thanks for any advice,
Mark
From here:
...the initializer should have been set in the static constructor of your context. The static constructor is called before any constructors and is executed once. This is what we want. The reason is that in some of your application, you may initialize more than once the context. You do not want to execute all the process to check if the database if ready to be changed or not.
So, you should change your class to have a static constructor that is only called one time.
namespace lhts2.Models
{
public class DefaultConnection : DbContext
{
static DefaultConnection()
{
Database.SetInitializer<DefaultConnection>(null);
}
public DefaultConnection() : base("name=DefaultConnection")
{
}
}
}
I had the same issue. Setting the IIS user to a "sysad" level user allowed the application to work normally. However that is not a secure method of solving the problem.
Further research revealed that the "migrations" table (named dbo.__MigrationHistory) was the culprit. I had given the IIS user access (Select, Update, Delete, Insert, and References) to all the "application" tables, but not the "migrations" table. Consequently when the application runs and attempts to determine if a migration is necessary, the access fails because of the lack of access rights for that user and the application thinks it needs to create the database and tables - which this user clearly should not have rights to do.
By providing normal access rights to the __MigrationHistory table (Select, Update, Delete, Insert, and References) the IIS user was now able to determine that no migration was necessary and therefore did not attempt to conduct a migration.
Example of Permission Settings Here
I am using Entity Framework 6 in a ASP.NET MVC application. I am using a Code First approach to try and connect to an existing database.
Firstly, I have set up a Model as follows:
public class Employee
{
public int ID { get; set; }
public string PAYCODE { get; set; }
}
Secondly, I have a Context as follows:
public class EmployeeContext : DbContext
{
public EmployeeContext()
: base("EmployeeDB")
{
}
public DbSet<Employee> Employees { get; set; }
}
Thirdly, I have specified the connection to the DB in the web.config:
<connectionStrings>
<add name="EmployeeDB" connectionString="Server=MyServer;Database=MyDB;User ID=MyUserID;Password=MyPassword;Trusted_Connection=False" providerName="System.Data.SqlClient" />
</connectionStrings>
Finally, I call my context from a Controller class as follows:
var db = new EmployeeContext();
However, this throws the following run-time error:
The Entity Framework provider type 'System.Data.Common.DbProviderConfigurationHandler, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' did not have a static property or field named 'Instance'. Entity Framework providers must declare a static property or field named 'Instance' that returns the singleton instance of the provider.
I would be extremely grateful if anyone can shed some light on this error - I have tried searching on the Web, and have followed Microsoft examples.
Many thanks!
Martin
Added in response to question below:
The following is at the foot of my web.config:
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
<provider invariantName="System.Data.OracleClient" type="System.Data.Common.DbProviderConfigurationHandler, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</providers>
I have found out that the error message was caused by trying to use 'System.Data.OracleClient' as a provider for EF6.
It looks to me that this provider cannot be used to connect to Oracle from an EF6 application.
After some searching, I am trying to replace the provider with Devart dotConnect, but the version that my company owns seems to be too out of date to support EF6.
There doesn't seem to be many resources to help with connecting EF6 to Oracle.
Looks like you need to change your connection factory to SqlConnectionFactory. http://blogs.msdn.com/b/davidobando/archive/2012/08/14/changing-ef-s-default-provider-from-localdb-to-sql-server.aspx
I am having the architecture like this :
Where MVC layer is the presentation layer. EF is class library and Repository is another class library.I am trying to insert data to database from repository by creating the EF context object. Added EF reference into Repository class library. EF having the edmx file. its app.config having the connection string generated by EF.
code is :
public bool CreateUser(User _user)
{
context.Users.Add(_user);
context.SaveChanges();
return true;
}
but while executing this I am getting following exception :
No connection string named 'MyEntitiesConnection' could be found in the application config file.
I tried to add same connection string with same name in repository app.config. but not working. anyone have solution ?
Edited:
connection string is :
<add name="MyEntitiesConnection" connectionString="metadata=res://*/EF.Entities.csdl|res://*/EF.Entities.ssdl|res://*/EF.Entities.msl;provider=System.Data.SqlClient;provider connection string="data source=Servername\MSSQL2008R2;initial catalog=MyDBName;persist security info=True;user id=sa;MultipleActiveResultSets=True;App=EntityFramework;" providerName="System.Data.EntityClient" />
app.config:
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<add name="MyEntitiesConnection" connectionString="metadata=res://*/EF.Entities.csdl|res://*/EF.Entities.ssdl|res://*/EF.Entities.msl;provider=System.Data.SqlClient;provider connection string="data source=Servername\MSSQL2008R2;initial catalog=MyDBName;persist security info=True;user id=sa;MultipleActiveResultSets=True;App=EntityFramework;" providerName="System.Data.EntityClient" />
</connectionStrings>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
</entityFramework>
</configuration>
In any .NET application, only one config file is the natural starting point for looking for configuration information. For web applications, that's the web.config file at the root of the application1.
Whilst you may have a file called app.config in your repository project (and, indeed, some VS tooling may have added one) or your EF project, it's not used when you try to read configuration information.
The connection string section needs to exist in the web.config of your MVC app.
1For non-web applications, it's the app.config for the project that produces the .exe file and that gets automatically copied as XXX.exe.config during the build.
I'm trying to set up Log4Net in a MVC.net project with Ninject.
I've reached the point where I'm able to see the Ninject debug output but I am still not seeing any logging output.
This is all running on my localhost so there shouldn't be any issues with security.
The setup I have is as follows:
In the AssemblyInfo.cs I have added this to point log4net to Web.config for configuration
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "Web.config", Watch = true)]
In the Web.config I've added the following sections
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net"/>
</configSections>
...
<appSettings>
<add key="log4net.Internal.Debug" value="true"/>
</appSettings>
...
<log4net>
<appender name="FileAppender" type="log4net.Appender.FileAppender">
<file value="log-file.txt" />
<appendToFile value="true" />
<encoding value="utf-8" />
<layout type="log4net.Layout.SimpleLayout" />
</appender>
<root>
<level value="ALL" />
<appender-ref ref="FileAppender" />
</root>
</log4net>
In my base controller, from which all the other controllers in the system inherit I have the following:
[Inject]
public ILogger logger { get; set; }
I then put an explicit throw new Exception("testException") on the login page to force an error which I would have expected to see showing up in the log file.
From the debug trace I see the following on startup.
log4net: log4net assembly [log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821]. Loaded from [C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\portal\63a118bb\781d84b7\assembly\dl3\40d137a6\9fb44da2_c951cc01\log4net.dll]. (.NET Runtime [4.0.30319.235] on Microsoft Windows NT 6.1.7601 Service Pack 1)
log4net: DefaultRepositorySelector: defaultRepositoryType [log4net.Repository.Hierarchy.Hierarchy]
log4net: DefaultRepositorySelector: Creating repository for assembly [Ninject.Extensions.Logging.Log4Net, Version=2.2.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7]
log4net: DefaultRepositorySelector: Assembly [Ninject.Extensions.Logging.Log4Net, Version=2.2.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7] Loaded From [C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\portal\63a118bb\781d84b7\assembly\dl3\edd36351\91af46a2_c951cc01\Ninject.Extensions.Logging.Log4Net.dll]
log4net: DefaultRepositorySelector: Assembly [Ninject.Extensions.Logging.Log4Net, Version=2.2.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7] does not have a RepositoryAttribute specified.
log4net: DefaultRepositorySelector: Assembly [Ninject.Extensions.Logging.Log4Net, Version=2.2.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7] using repository [log4net-default-repository] and repository type [log4net.Repository.Hierarchy.Hierarchy]
log4net: DefaultRepositorySelector: Creating repository [log4net-default-repository] using type [log4net.Repository.Hierarchy.Hierarchy]
I have the feeling that this is probably a configuration issue but any help would be appreciated.
Injecting an ILog or ILogger instance does not implicitly register any kind of exception handler. It just gives you access to a logger. You still have to tell it what to log and when to log it.
If you want to test your configuration, make a logging call from one of your controller's actions, or use one of the OnAction event invokers. This should probably do what you want:
public class MyController : Controller
{
protected override void OnActionExecuted(ActionExecutedContext context)
{
if (Logger != null)
{
string message = string.Format("Action executed: {0}.{1}",
context.ActionDescriptor.ControllerDescriptor.ControllerName,
context.ActionDescriptor.ActionName);
Logger.Log(typeof(MyController), log4Net.Core.Level.Trace,
message, context.Exception);
}
base.OnActionExecuted(context);
}
[Inject]
public ILogger Logger { get; set; }
}
That will log every controller action - including exceptions. If you only care about exceptions then either check the context.Exception and context.ExceptionHandled properties before logging, or better yet write a custom ActionFilter to do this.