Unable to setup MiniProfiler w/ Enity Framework 4.0 (Not code first) - asp.net-mvc-3

I installed MiniProfiler and MiniProfiler.EF in my project via nuget.
Before using MiniProfiler I would open a connection using this in my model repository:
public class NotificationRepository
{
private CBNotificationModel.CB_NotificationEntities db;
public NotificationRepository()
{
db = new CB_NotificationEntities();
}
public NotificationContact GetNotificationContacts()
{
return db.NotificationContacts.ToList();
}
}
To use mini profiler I created:
public static class ConnectionHelper
{
public static CB_NotificationEntities GetEntityConnection()
{
var conn = new StackExchange.Profiling.Data.EFProfiledDbConnection(GetConnection(), MiniProfiler.Current);
return ObjectContextUtils.CreateObjectContext<CB_NotificationEntities>(conn); // resides in the MiniProfiler.EF nuget pack
}
public static EntityConnection GetConnection()
{
return new EntityConnection(ConfigurationManager.ConnectionStrings["CB_NotificationEntities"].ConnectionString);
}
}
The model repository now uses
db = ConnectionHelper.GetEntityConnection();
However this gives the error:
An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll
Am I missing a step? I tried adding MiniProfilerEF.Initialize() and MiniProfilerEF.Initialize_EF42() in Application_start() however that just changes the errors given.
There does not seem to be much information for setting up a entity framework project to use miniprofiler unless it is codefirst.

I was able to get this working by changing my ConnectionHelper class to the following:
public static class ConnectionHelper
{
public static CB_NotificationEntities GetEntityConnection()
{
var connectionString = ConfigurationManager.ConnectionStrings["CB_NotificationEntities"].ConnectionString;
var ecsb = new EntityConnectionStringBuilder(connectionString);
var sqlConn = new SqlConnection(ecsb.ProviderConnectionString);
var pConn = new StackExchange.Profiling.Data.EFProfiledDbConnection(sqlConn, MiniProfiler.Current);
var context = ObjectContextUtils.CreateObjectContext<CB_NotificationEntities>(pConn);
return context;
}
}

Related

How to work with an DevArt edml file and start a connection?

I am working with the newest DevArt Oracle version and created a EDML file that connects to my Oracle 12 database and get the models with the db first approach.
I followed this howto:
https://www.devart.com/entitydeveloper/docs/
So I have my context and my model auto generated:
public partial class KiddataAdminEntities : DbContext
{
#region Constructors
/// <summary>
/// Initialize a new KiddataAdminEntities object.
/// </summary>
public KiddataAdminEntities() :
base(#"name=KiddataAdminEntitiesConnectionString")
{
Configure();
}
/// <summary>
/// Initializes a new KiddataAdminEntities object using the connection string found in the 'KiddataAdminEntities' section of the application configuration file.
/// </summary>
public KiddataAdminEntities(string nameOrConnectionString) :
base(nameOrConnectionString)
{
Configure();
}
private void Configure()
{
this.Configuration.AutoDetectChangesEnabled = true;
this.Configuration.LazyLoadingEnabled = true;
this.Configuration.ProxyCreationEnabled = true;
this.Configuration.ValidateOnSaveEnabled = true;
}
#endregion
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Anrede> Anrede { get; set; }
}
Now I try to get it to work in my main in another project (just a simple console application with a start.cs):
KiddataAdminEntities context = new KiddataAdminEntities("User Id=xxxx;Password=xxxx;Server=xx;Direct=True;Sid=xxxx;Persist Security Info=True");
var listOfAnrede = context.Anrede.ToList();
So now I get the error "Keyword user id not supported".
I googled this and I found out that problably EF6 is trying to get a default connection, not an oracle connection with DevArt...
I tried to play with the app.config in different ways but it didnt help.
Now I tried to create my own connection with the DevArt.Data.Oracle provider, like shown here:
https://www.devart.com/dotconnect/oracle/articles/tutorial-connection.html
OracleConnection oc = new OracleConnection();
oc.ConnectionString = constring2;
oc.Open();
var test = oc.ServerVersion;
This works fine, so the connectionstring is okay, but still I can't put these two together. I tried to overload the constructor so I can put in my Connection:
public KiddataAdminEntities(DbConnection con, bool contextOwnsConnection)
: base(con, contextOwnsConnection)
{
}
Then I got the error on
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
That I should not do that...
If you are using XML mapping with Devart Entity Model (*.edml), try this code:
using Devart.Data.Oracle;
using System.Data.EntityClient;
...
OracleConnectionStringBuilder oracleBuilder = new OracleConnectionStringBuilder();
oracleBuilder.UserId = "...";
oracleBuilder.Password = "...";
oracleBuilder.Server = "...";
oracleBuilder.Direct = true;
oracleBuilder.Sid = "...";
oracleBuilder.PersistSecurityInfo = true;
EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
entityBuilder.Provider = "Devart.Data.Oracle";
entityBuilder.ProviderConnectionString = oracleBuilder.ConnectionString;
entityBuilder.Metadata = #"res://*/MyModel.csdl|res://*/MyModel.ssdl|res://*/MyModel.msl";
using (Entities context = new Entities(entityBuilder.ToString())) {
var a = context.MyEntity.First();
}
Refer to
https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/ef/how-to-build-an-entityconnection-connection-string
https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/ef/connection-strings
FYI, you can generate fluent mapping (instead of XML mapping). For this, disable a predefined EntityObject template, enable the DbContext template and set the options:
Fluent Mapping=True in the properties of DbContext template
Metadata Artifact Processing=Do Not Generate Mapping Files in the properties of EntityContextModel

SQLiteAsyncConnection UpdateWithChildren not available

I am trying to implement a OneToMany relationship inside my PCL using SQLite.net. I have the async extensions package (SQLiteNetExtensions.Async) and I am basing the code on the example found in https://bitbucket.org/twincoders/sqlite-net-extensions. I am using SQLiteAsyncConnection but the UpdateWithChildren method does not seem to be available, only with SQLiteConnection.
using SQLite.Net;
using SQLite.Net.Async;
using SQLite.Net.Interop;
using SQLiteNetExtensions.Extensions;
private readonly SQLiteAsyncConnection conn;
public ActivityRepository(ISQLitePlatform platform, string dbPath)
{
var connectionFactory = new Func<SQLiteConnectionWithLock>(() => new SQLiteConnectionWithLock(platform, new SQLiteConnectionString(dbPath, storeDateTimeAsTicks: true)));
conn = new SQLiteAsyncConnection(connectionFactory);
}
public void method(object object) {
conn.UpdateWithChildren(object); --function not available
}
When using SQLiteAsyncConnection, you have to use the async Nuget package, SQLiteNetExtensionsAsync.Extensions namespace and async versions of all the methods:
using SQLite.Net;
using SQLite.Net.Async;
using SQLite.Net.Interop;
using SQLiteNetExtensionsAsync.Extensions;
private readonly SQLiteAsyncConnection conn;
public ActivityRepository(ISQLitePlatform platform, string dbPath)
{
var connectionFactory = new Func<SQLiteConnectionWithLock>(() => new SQLiteConnectionWithLock(platform, new SQLiteConnectionString(dbPath, storeDateTimeAsTicks: true)));
conn = new SQLiteAsyncConnection(connectionFactory);
}
public Task method(object object) {
return conn.UpdateWithChildrenAsync(object);
}
Please note that all async methods return a Task that must be awaited or returned.

Autofac with MEF integration

I need help. I create Windows Service with Autofac container.
And I use MEF Integration service for create several alternative components for my service.
For example:
Module 1
[Export(typeof(IClass1))]
public class Class1 : IClass1
{
public void Show()
{
Console.WriteLine("Hallo from Class1");
}
}
Module 2
[Export(typeof(IClass2))]
public class Class2 : IClass2
{
public void Show()
{
Console.WriteLine("Hallo from Class2");
}
}
Basic class for modules integration - example
class Program
{
private static IContainer Container { get; set; }
static void Main(string[] args)
{
// Create your builder.
var builder = new ContainerBuilder();
/** find all modules in selected folder */
var catalog = new DirectoryCatalog(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + #"\modules", "*Module.dll");
/** register finded modules */
builder.RegisterComposablePartCatalog(catalog);
builder.RegisterType<MyClass>().As<IMyClass>().SingleInstance();
Container = builder.Build();
var cls = Container.Resolve<IMyClass>();
cls.Show();
Console.WriteLine("Class ready. Press Enter");
Console.ReadKey(true);
}
}
class MyClass: IMyClass
{
private readonly IClass1 _class1;
private readonly IClass1 _class3;
private readonly IClass2 _class2;
private readonly IClass2 _class4;
public MyClass(IClass1 class1, IClass2 class2)
{
_class1 = class1;
_class2 = class2;
_class3 = class1;
_class4 = class2;
}
public void Show()
{
_class1.Show();
Console.WriteLine("Class1 ready. Press Enter");
Console.ReadKey(true);
_class2.Show();
Console.WriteLine("Class1 ready. Press Enter");
Console.ReadKey(true);
}
}
internal interface IMyClass
{
void Show();
}
In this example all work fine.This principle I use in my service. For test start and debug my service I use Service.Helper from Nuget packages repository.
Everithyng work fine too.
But. If i create install package in Advance installer and install my service in system (Windows 8.1 x64) service do not start.
Logging exception from service write System.ArgumentNullException in system Event log. Exception most likely in this line
builder.RegisterComposablePartCatalog(catalog);
Service do not load any modules from start folder. Access denied from service to his subfolder. Help please. Thanks.
Try Assembly.GetEntryAssembly().Location insted of Assembly.GetExecutingAssembly().Location

odata ApiController.User == NULL after upgrade to web api 5.0.0-rc1

I'm using Windows Auth and it was working fine on this odata controller. But after I got the latest NuGet package (prerelease 5.0.0-rc1) something changed and ApiController.User is null. It's not passing the Windows Auth anymore. Any ideas? I tried adding the [Authorize] attribute but that didn't work - maybe that needs more config somewhere else.
public class ProductsController : EntitySetController<Product, int>
{
protected ProjectContextUnitOfWork UoW;
protected UserRepository UserRepo;
protected ProductRepository ProductRepo;
protected Project.Models.User CurrentUser;
// odata/Products/
public ProductsController()
{
if (!User.Identity.IsAuthenticated)
{
HttpResponseMessage msg = Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "User not authenticated.");
throw new HttpResponseException(msg);
}
ProjectUserPrincipal LoggedInUser = this.User as ProjectUserPrincipal;
// - closed in Dispose()
UoW = new ProjectContextUnitOfWork(false); //without lazy loading
UserRepo = new UserRepository(UoW);
ProductRepo = new ProductRepository(UoW);
CurrentUser = UserRepo.Get(LoggedInUser.Username, LoggedInUser.Domain);
}
protected override Product GetEntityByKey(int id)
{
var x = from b in ProductRepo.GetAvailableProductsWithNumbers(CurrentUser)
where b.Id == id
select b;
return x.FirstOrDefault();
}
...
}
Other details:
.NET 4.5
Web Forms
Also, when I reverted back to 5.0.0.beta2, without any other changes, it works again. So it's definitely a change in Microsoft.AspNet.WebApi. I'm ok with making code changes, I just need some tips. Thanks!
It's because you are using the ApiController.User in controller constructor. At that time, the property has not been initialized. You should:
Add [Authorize] attribute on your controller
Move the initialization code in Initialize method
So the code looks like:
[Authorize]
public class ProductsController : EntitySetController<Product, int>
{
protected override void Initialize(System.Web.Http.Controllers.HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
ProjectUserPrincipal LoggedInUser = this.User as ProjectUserPrincipal;
// - closed in Dispose()
UoW = new ProjectContextUnitOfWork(false); //without lazy loading
UserRepo = new UserRepository(UoW);
ProductRepo = new ProductRepository(UoW);
CurrentUser = UserRepo.Get(LoggedInUser.Username, LoggedInUser.Domain);
}
}

How to pass a mvc-mini-profiler connection to a base class from MVC3

Given this snippet of code
public abstract class Foo
{
private static SqlConnection _sqlConnection;
protected SqlConnection GetOpenConnection()
{
if (_sqlConnection == null)
{
_sqlConnection = new SqlConnection("connection string");
}
return _sqlConnection;
}
protected abstract void Execute();
}
public class FooImpl : Foo
{
protected override void Execute()
{
var myConn = GetOpenConnection();
var dog = myConn.Query<dynamic>("select 'dog' Animal");
var first = dog.First();
string animalType = first.Animal;
// more stuff here
}
}
How would you wrap the connection in a profiled connection if you don't have access to the connection creation process? Rewrite the code in the super class and wrap it there? This would involve changing hundreds of classes that inherit from the base. I'd prefer a way to change the base class, with as little changes necessary to the supers.
Thank you,
Stephen
Well after a bit of trial and error I compromised and added a ref to MvcMiniProfiler in the base library and changed the connection code a bit.
protected DbConnection GetOpenConnection()
{
if (_connection == null)
{
_connection = new SqlConnection(ConfigurationManager.ConnectionStrings["connection string "].ConnectionString);
_connection.Open();
}
return MvcMiniProfiler.Data.ProfiledDbConnection.Get(_connection, MiniProfiler.Current);
}
private static SqlConnection _connection;
This works for both hosting in the MVC project (for profiling purposes, where we don't have that capability (QA/Prod Databases)) and WPF/Windows Service

Resources