MiniProfiler with EF "model first" edmx model - asp.net-mvc

I'm trying to get MiniProfiler to profile my database access but I'm running into problems. All the help I see out there seems to be for "code first" entity framework connections. My model was designed before the code first update was available this year and I used the designer to create the edmx model. (I've been using this for almost a year and it seems to be working for me)
The example on the MiniProfiler documentation site doesn't make sense to me. I've tried a few variations of it but I'm having problems.
My Model is called CYEntities, normally to instantiate an ObjectContext I just do this
var context = new CYEntities() here's what I've tried for the profiler...
var dbConnection = new CYEntities().Connection;
var profiledConnection = ProfiledDbConnection.Get(dbConnection);
var context = profiledConnection.CreateObjectContext<CYEntities>(); // this is the context I'd finally use to access data.
This throws an exception...
System.ArgumentException: Unable to find the requested .Net Framework Data Provider. It may not be installed.
I'm not sure where to go from here.

Try like this:
var connectionString = ConfigurationManager
.ConnectionStrings["MyConnectionString"]
.ConnectionString;
var ecsb = new EntityConnectionStringBuilder(connectionString);
var sqlConn = new SqlConnection(ecsb.ProviderConnectionString);
var pConn = ProfiledDbConnection.Get(sqlConn, MiniProfiler.Current);
var context = ObjectContextUtils.CreateObjectContext<CYEntities>(pConn);

I'm having the same issue. It appears that you must add the following to your web.config, however, for me this causes the w3wp.exe process to crash (and the web server in visual studio, for local requests). It doesn't seem like something that is happening to anyone else, so it might work for you (make sure to insert the actual version of the profiler you are using).
<system.data>
<DbProviderFactories>
<remove invariant="MvcMiniProfiler.Data.ProfiledDbProvider" />
<add name="MvcMiniProfiler.Data.ProfiledDbProvider" invariant="MvcMiniProfiler.Data.ProfiledDbProvider" description="MvcMiniProfiler.Data.ProfiledDbProvider" type="MvcMiniProfiler.Data.ProfiledDbProviderFactory, MvcMiniProfiler, Version=1.7.0.0, Culture=neutral, PublicKeyToken=b44f9351044011a3" />
</DbProviderFactories>
</system.data>

Related

how to modify a DbSet at an specific time?

I am working on an ASP NET MVC 5 website and I want to modify an element of a DbSet only once at the start of a new day, month and year, but I can't find any example on the internet doing this, any help on how to do this?
lets say I have:
public class File
{
public int FileID { get; set; }
public int Votes { get; set; }
}
and
public DbSet<File> Files { get; set; }
and I want to change a file votes to 0 at the start of a new day only once:
var modFile = new File{ FileID = 2, Votes = 0};
db.Entry(modFile).State = EntityState.Modified;
db.SaveChanges();
Where in a MVC 5 project do I put this code?
How it gets triggered?
If you have an external Service layer (that is independent of .NET) which contains your objects (in your case, File.cs, etc..) then using the built-in Windows scheduler is fine (it triggers executable code at a certain time, as defined by the user).
To do this, you may want to create a Console Application that has a reference to the Service dll and the connection of your database.
Console Application
In Visual Studio, go to File -> New Project -> Visual C# -> Console Application.
Within the App.config file, you can add the connection string to your database. For example:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="SchoolDBConnectionString"
connectionString="Data Source=...;Initial Catalog=...;Integrated Security=true"
providerName="System.Data.SqlClient"/>
</connectionStrings>
</configuration>
You can then set up a reference to your Service.dll which should have the database context accessible, e.g. DataContext db = MyService.Data.DataContext();
So instead of:
var modFile = new File{ FileID = 2, Votes = 0};
db.Entry(modFile).State = EntityState.Modified;
db.SaveChanges();
You could use:
db.Files.Where(s => s.Votes > 0).ToList().ForEach(s => s.Votes = 0);
db.SavesChanges();
You can run the project in release mode and grab the relevant dll's and exe file. Within the Task Scheduler you are then able to create a task that runs a specific exe.
Service
Technically speaking, you don't have to have this level of isolation -- but in my opinion it's good practice. You could just create a reference to your MVC project, but I personally wouldn't.
To create a Service layer..
Right click your solution (where your MVC application is within) -> Add -> New Project -> Visual C# -> Class Library
Within this project, you should move all your objects (File.cs, etc) within here. You are then able to create a reference to this project within your MVC project by right clicking References and selecting the Service library you just created. You can do the same for the Console Application.
This will then create a layer of isolation between your MVC application and concrete (business) logic.
Otherwise, if you have to schedule your tasks within ASP.NET check out Scott Hanselman's post -- he has compiled together a list of libraries that schedule jobs at certain times. It's however important to understand that ASP.NET applications should only really deal with user requests and responses - threads are somewhat dangerous.

Issue unit testing an asp.net MVC controller that inherits from a custom base controller

So i'm using Moq and starting to write unit tests for my controller actions.
All of my controllers inherit from a base CustomController class that provides a userId property set in the constructor to be the value of Membership.GetUser().ProviderUserKey. This way I can pass the userId to my service layer simply by passing contactId.
This does not seem to work well with this unit test:
var serviceMock = new Mock<IFormService>();
serviceMock.Setup(g => g.GetForm(2)).Returns(new FormViewModel() {ID = 2, Name = "Mock Form"});
var controller = new FormController(serviceMock.Object);
var result = controller.Index(2);
Assert.IsNotNull(result, "View Result is null");
It throws an exception on the base CustomController where it tries to set the userId from Membership.GetUser().ProviderUserKey.
"UnauthorizedAccessException: Access to the path 'C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow\App_Data' is denied."
Has anyone else come across this issue or have any thoughts on a way around it?
You maybe forget to set the membership provider in your webconfig:
<system.web>
<membership defaultProvider="SqlProvider" userIsOnlineTimeWindow="20">
</system.web>

Code-first always working with SQL Server Express or SQL Server CE

I'm building a MVC 3 application and use Entity Framework 4.3 code-first. My context is becoming complex so I've decided to working with SQL Server 2008 R2. Then I changed my connection string in web.config. I checked and I know the new connection string is correct, but EF is still working with the default connection string (.\SQLEXPRESS ...) from SQL Server CE (I have now deleted SQL Server CE from nuget packages).
My context name is CodeFirstContext and my connection string name is CodeFirstContext, too. But the return context.Products; always fails and/because the connection string in context says SQLEXPRESS (my web.config sets the connection string to SQLSERVER).
What is going on here? I erased all default connection strings in the project. When I am running the project, it still gets all data from SQL Server Express.
I have been searching for about two days. Why is this so difficult if so many people only have to change the connection string and then it works.
You might be picking up the connection string from your root/machine config, in your web.config file add a clear element like so
<connectionStrings>
<clear/>
.. your connection strings here
...
I 've solved the problem like that:
public class CodeFirstContext : DbContext
{
public CodeFirstContext() : base("RandevuIzle")
{
}
public DbSet<User> Users { get; set; }
}
<connectionStrings>
<add name="RandevuIzle" connectionString="Data Source=111.222.333.444\MSSQLSERVER2008; Initial Catalog=RandevuIzle;User Id=MyUserName;Password=myPassword" providerName="System.Data.SqlClient" />
Somethings went wrong but i cannot understand. I re-start the project after doing this code below. Then it's work normally.
As you instantiate your DbContext, are you providing a name that isn't CodeFirstContext?
Holy SQL Smoke, Batman! This drove me totally batty today. Getting EF 5.0 up and running w/ VS2010 on a new project was much more difficult than I imagined. I had the same problem and found this great Ode to the Code ::
http://odetocode.com/blogs/scott/archive/2012/08/15/a-troubleshooting-guide-for-entity-framework-connections-amp-migrations.aspx
And to be specific ::
public class DepartmentDb : DbContext
{
public DepartmentDb()
: base(#"data source=.;
initial catalog=departments;
integrated security=true")
{ }
public DbSet<Person> People { get; set; }
}
Got me the result I was needing. Do I think it's cool that I've got to set the data source like this and that it won't find the obvious solution within the app.config? No, I don't. But I have officially spent too much time attempting a transition from LINQ to SQL over to EF today and am going to go ahead and get some of the application done while I still have some interest in doing so.

Connection string for using SQL Server Compact with Entity Framework?

I'm done trying to Google for this. I have installed SQL Server CE 4.0, and have EF 4.1, but I can't get a proper connection string. Nothing on connectionstrings.com applies to me.
I just want to create a SqlCeEngine object, but no matter what I try I get some exception. Most recently it's been
Unknown connection option in connection string
with either "metadata", "app", "provider", or "provider connection string" after it. I know EF requires metadata in the connection string. And I can't imagine how anything could do without "provider connection string".
So far I have this:
<add name="DBContext"
connectionString="provider connection string="Data Source=MyDbFile.sdf;Persist Security Info=False;""
providerName="System.Data.EntityClient" />
At one point I had it with metadata:
<add name="DBContext"
connectionString="metadata=res://*/Data.DBContext.csdl|res://*/Data.DBContext.ssdl|res://*/Data.DBContext.msl;provider=System.Data.SqlClient;provider connection string="Data Source=MyDbFile.sdf;Persist Security Info=False;""
providerName="System.Data.EntityClient" />
Does it need metadata or not? What goes in the "app" part of the connection string? What should the provider be, System.Data.SqlClient or some SQL Server CE version? (which I still can't find when I try to add references. My add references window still only contains System.Data.SqlServerCe version 3.5.1.0.) Or nothing?
And what should go in the providerName attribute? Is System.Data.EntityClient correct? It's like there are 10 different variables here and every combination gives me a new equally mysterious error, none of which turns up anything useful on Google. I'm at my wits' end. Is this even possible?
You could try this in your App.config file (EF5 Code first migrations and SQL Server CE 4.0):
<connectionStrings>
<add name="DefaultConnection"
providerName="System.Data.SqlServerCe.4.0"
connectionString="Data Source=|DataDirectory|\Data\ProjectDb.sdf"/>
</connectionStrings>
And in you ProjectDb class:
class ProjectDb : DbContext
{
public ProjectDb()
: base("DefaultConnection")
{
}
}
It will work like a charm.
You can find more information here: http://blogs.msdn.com/b/adonet/archive/2011/01/27/using-dbcontext-in-ef-feature-ctp5-part-2-connections-and-models.aspx
I’d stuck with the same problem on Entity Framework 5.0 Code First approach with SQL Server Compact Edition 4.0
To solve it I pass instance of SqlCeConnection to DbContext's constructor:
public class Storage : DbContext
{
public Storage()
: base(new SqlCeConnection("Data Source=Database.sdf;Persist Security Info=False;"),
contextOwnsConnection: true)
{ }
//...
}
If you don’t want to inline connection string you could get it from App.config through ConfigurationManager
And of course you should add reference to the right version of System.Data.SqlServerCe (look inside Extentions tab in the Add Reference dialog)
This TechNet article outlines the steps for using EF with SQL Server Compact. This line jumped out at me, and may solve your problems:
make sure that provider=System.Data.SqlServerCe.3.5 in the connection
string.
(I would assume that you would want 4.0 instead of 3.5)
Give that a try and see how things go.
The Lu55's solution didn't work for me, but I found fow to fix it. To still use the automatic code generation (which can overwrite changes in a generated file), I added one more file with the following code:
using System.Data.Entity;
using System.Data.Objects;
namespace MyProject.Data
{
internal partial class Entities : DbContext
{
public Entities(string connectionString)
: base(
new ObjectContext(
#"metadata=res://*/Data.Model.csdl|
res://*/Data.Model.ssdl|
res://*/Data.Model.msl;
provider=System.Data.SqlServerCe.4.0;"),
true)
{
Database.Connection.ConnectionString = connectionString;
}
}
}
You have mixed a bit.
For SQL Server CE connection string can be quite easy (possibly replace DbContext with YourNameSpace.DbContextName):
<add name="DbContext"
connectionString="MyDbFile.sdf"
providerName="System.Data.SqlServerCe.4.0" />
I also had a lot of trouble with connections, so I did the following:
installed Entity Framework for SQL Server CE
Checked that web.config contains provider with invariant System.Data.SqlServerCe.4.0
Verified that there are NO string fields (which will be represented as columns in db) with length max or mode than 4000 symbols (to add restriction use annotation [MaxLength(4000)], by default == MAX)
Metadata are necessary when you use database-first model instead of code-first, so there is .edmx file which represents generated model of the database.

DataContext crashes when unit testing

I am using Linq to SQL in my project. I have a part of the code that calls
DataContext db = new DataContext()
This works as expected when running the website however when calling this from within my unit test I get an error object not set to an instance...
Do you know why this is?
I know I should Mock the data context for testing but there is only two tests that use this that I need completed for this stage of the project. Then I will go in and Mock.
I just don't see why it doesn't work.
Edit:
In my controller I have the line
CandidateRegistrationViewModel viewModel = new CandidateRegistrationViewModel("PersonalDetails", candidate);
The Model has a member db:
public class CandidateRegistrationViewModel
{
private EmployDirectDataContext db = new EmployDirectDataContext();
This class then uses db to populate select boxes.
It all works when I run but in the unit test I get an error upon creating the datacontext.
[TestMethod]
public void PersonalDetailsStepPostShouldRedisplayIfDOBSuppliedInWrongFormat()
{
// Arange
var controller = CreateCandidateController("Dean");
repository.Add(FakeCandidateData.CreateCandidate(controller.member.UserId()));
FormCollection formCollection = FakeCandidateData.CreatePersonalDetailsStepFormCollection();
formCollection["DOB"] = "24/2009/87"; //DOB in wrong format - should be dd/mm/yyyy
controller.ValueProvider = formCollection.ToValueProvider();
// Act
ViewResult result = (ViewResult)controller.PersonalDetailsStep(formCollection);
// Assert
Assert.AreEqual("", result.ViewName); //ViewName is returned as empty if same as Action name
}
Both of the projects have the same connection string in the app/web.config
<add name="EmployDirectDBConnectionString" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\EmployedDirectDB.MDF;Integrated Security=True;User Instance=True"
providerName="System.Data.SqlClient" />
Testing the Data Context falls more into the purview of an Integration Test. The mocks are more appropriate for your repository interface. Your repository will hold a valid reference to the DataContext object during your integration testing.
Your unit test assembly probably does not have the right connectionstring compiled into the settings. That's why I always use:
var db = new MyDataContext(SomeConfigClassIMade.ConnString) {...}
so I can more tightly control how the connection string works,.
I an not sure why you would want to test the DataContext itself... (I may be wrong and I am sure someone will tell me if I am) but would you just test the DataAccess or Repository class that uses the DataContext...
Other than that it probably just doesn't have the correct connection string...

Resources