"Specified method is not supported" in Entity Framework - c#

This is my entity class:
public partial class NerdDinnerEntities : ObjectContext
{
public NerdDinnerEntities(string connectionString)
: base(connectionString, "NerdDinnerEntities")
{
try
{
ObjectContext oc = new ObjectContext(connectionString);
oc.Connection.ChangeDatabase("NERDDINNER1");
oc.AcceptAllChanges();
this.ContextOptions.LazyLoadingEnabled = true;
OnContextCreated();
}
catch (Exception ex) { }
}
partial void OnContextCreated();
/// <summary>
/// No Metadata Documentation available.
/// </summary>
public ObjectSet<Dinner> Dinners
{
get
{
if ((_Dinners == null))
{
_Dinners = base.CreateObjectSet<Dinner>("Dinners");
}
return _Dinners;
}
}
private ObjectSet<Dinner> _Dinners;
/// <summary>
/// No Metadata Documentation available.
/// </summary>
public ObjectSet<RSVP> RSVPs
{
get
{
if ((_RSVPs == null))
{
_RSVPs = base.CreateObjectSet<RSVP>("RSVPs");
}
return _RSVPs;
}
}
private ObjectSet<RSVP> _RSVPs;
/// <summary>
/// No Metadata Documentation available.
/// </summary>
public ObjectSet<sysdiagram> sysdiagrams
{
get
{
if ((_sysdiagrams == null))
{
_sysdiagrams = base.CreateObjectSet<sysdiagram>("sysdiagrams");
}
return _sysdiagrams;
}
}
private ObjectSet<sysdiagram> _sysdiagrams;
/// <summary>
/// Deprecated Method for adding a new object to the Dinners EntitySet. Consider using the .Add method of the associated ObjectSet<T> property instead.
/// </summary>
public void AddToDinners(Dinner dinner)
{
base.AddObject("Dinners", dinner);
}
/// <summary>
/// Deprecated Method for adding a new object to the RSVPs EntitySet. Consider using the .Add method of the associated ObjectSet<T> property instead.
/// </summary>
public void AddToRSVPs(RSVP rSVP)
{
base.AddObject("RSVPs", rSVP);
}
/// <summary>
/// Deprecated Method for adding a new object to the sysdiagrams EntitySet. Consider using the .Add method of the associated ObjectSet<T> property instead.
/// </summary>
public void AddTosysdiagrams(sysdiagram sysdiagram)
{
base.AddObject("sysdiagrams", sysdiagram);
}
}
and these is my web.config file as
<add name="NerdDinnerEntities" connectionString="metadata=res://*/Models.NerdDinner.csdl|res://*/Models.NerdDinner.ssdl|res://*/Models.NerdDinner.msl;provider=System.Data.SqlClient;provider connection string="Data Source=#;Database=NERDDINNER;User ID=#;Password=###;MultipleActiveResultSets=True"" providerName="System.Data.EntityClients" />
and i am getting error:
Specified method is not supported
in this line:
oc.Connection.ChangeDatabase("NERDDINNER1");

If you look up the docs at MSDN you will see that the method literally is not supported. It must be a placeholder for future improvements or something.
To expand for those who do want to change the database at runtime:
1.Create an entry in your settings to use in-place of the default in the app.config. Pull out the specifics, like Username, password, catalog name (database name), server etc into other settings entries.
<Setting Name="EntityConnectionString2" Type="System.String" Scope="Application">
<Value Profile="(Default)">metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;provider connection string="data source={0};initial catalog={1};persist security info=True;user id={2};password={3};encrypt=True;trustservercertificate=True;multipleactiveresultsets=True;App=EntityFramework"</Value>
</Setting>
Please note the {0}..{3} entries & that this connection string is not the whole configuration/connectionStrings/add entry in the app.config
2.Use one of the overloaded constructors for the EF Database that accepts a connection string.
var settings = Properties.Settings.Default;
string constring = string.Format(settings.EntityConnectionString2, settings.Server, settings.Database, settings.User, settings.Password);
NerdDinnerEntities db = new NerdDinnerEntities (constring);
3.To change at runtime you can create a different object in the same manner with a different catalog name, or dispose and recreate the db object with a different catalog name.

ChangeDatabase method of EntityConnection is not supported (http://msdn.microsoft.com/en-us/library/system.data.entityclient.entityconnection.changedatabase.aspx)
If you want to use your data context with another database, create another connection string and create data context instance using new connection string

Related

Can I somehow use different existingConnection in same entity DatabaseContext?

I need to use same entity DatabaseContext constructor for different connections (between sqlite and mysql). The connection string can changes (for both connections), so i can't use definied connectionString in App.config (or I need to change it somehow).
Two DatabaseContexts
UPDATE:
Here's code from pic above where I use different entity DatabaseContext constructors. In comment of first constructor shown unworking code how I want to use it (different database connections in same constructor).
/// <summary>
/// Sqlite database connection
/// </summary>
/// <param name="connectionString"></param>
public DatabaseContext(string connectionString) : base(new SQLiteConnection() {ConnectionString = connectionString}, true)
{
//base.Configuration = new MySqlConnection();
//base.Configuration = new SQLiteConnection() {ConnectionString = connectionString}, true);
}
/// <summary>
/// MySql database connection
/// </summary>
/// <param name="connectionString"></param>
/// <param name="mock">Identifies mysql connect</param>
public DatabaseContext(string connectionString, bool mock) : base(new MySqlConnection() {ConnectionString = connectionString}, true)
{
}

How do I resolve HttpContext from a RegisterEvent to retrieve a View in a string in asp.net core 3and Electron.net?

I've tried Dependency injection, but that always gives me a HttpContextAccessor.Current or ActionContext as null because I'm not in a request state (I think). So how can I get this context to just take a view, transform it to a html string (with Model if necessary) and throw it back in JS ? I even tried to call directly the Controller action, but it always gives HttpContext as null... I'm using Asp.NET Core 3.
Please, if someone has been going through, help me :-)
Thanks,
Edit:
I have an asp.net core based on Electron.net for a desktop application. I use a lot of IPC communication to retrieve data from backend c# using Electron.IpcMain.On. I register an action as listener in c# in a class. The main problem is that this class is really outside a normal HttpRequest or a Controller. Here is some sample code:
IpcBase Class
public abstract class IpcBase: IBaseIpcCommunicationClass
{
/// <summary>
/// Find a way to get rid of this and take more than the first window
/// </summary>
protected static BrowserWindow _mainWindow = Electron.WindowManager.BrowserWindows.First();
/// <summary>
/// Send an ipcEvent with a parameter class
/// </summary>
/// <param name="parameters">Parameters to fill</param>
public void RegisterIpcEvent<T>(IpcRegisterModel<T> registerModel) => Electron.IpcMain.On(registerModel.key, o => registerModel.action((T)
((JObject)o).ToObject(typeof(T))));
/// <summary>
/// Send a reply inside a registerevent
/// </summary>
/// <typeparam name="T">Type of model</typeparam>
/// <param name="model">model</param>
public void SendReply<T>(IpcSendParamsModel<T> model)
{
if (!string.IsNullOrEmpty(model.replyTo))
{
Electron.IpcMain.Send(_mainWindow, model.replyTo, model);
}
}
...
}
IpcUI (to get the controller view, just like an ajax call on a controller that retrieve the view in String (I already have that, but not with Ipc)
public class IpcUI: IpcBase
{
public IpcUI(IRazorViewToStringService razorViewRenderService)
{
Console.WriteLine("IpcUI::Constructor");
RegisterIpcEvent(new IpcRegisterModel<IpcSendParamsModel<AjaxPartialModel>>("renderPartial", async (param) =>
{
var param = new IpcSendParamsModel<AjaxPartialModel>("RenderPartial")
{
key = "renderPartial",
model = new AjaxPartialModel()
{
DataModel = "{items: [{\r\n MaterialIcon: \"\",\r\n Title: \"Games\",\r\n Selectable: true,\r\n Active: true,\r\n Key: \"GAMES\",\r\n BadgeCaption: \"new\",\r\n BadgeValue: \"123\",\r\n BadgeColor: \"red darken-1\",\r\n BadgePartialLink: \"\",\r\n BadgeContainerLink: \"\",\r\n BadgeModelLink: \"\",\r\n PartialLink: \"Home/Index\",\r\n ContainerLink: \"#body-content\",\r\n ModelLink: \"\"\r\n }] }".JsonDeserialize<MenuModelHeader>(),
PartialName = "PartialViews/_TopMenu"
}
};
try
{
param.results =
await razorViewRenderService.CreateAndResolveInstanceFromGeneric().RenderViewToStringAsync($"~/Views/{param.model.PartialName}.cshtml",
param.model.DataModel);
}
catch (Exception e)
{
IpcClasses.ExceptionManager.SendException(this, e, $"IpcUI params: {param.model.JsonSerialize()}");
}
}));
}
}
Razor Service (Mostly taken from here Generate string from view)
Added in startup:
services.AddHttpContextAccessor();
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
services.AddScoped<IRazorViewToStringService, RazorRazorViewToStringService>();
When I create an instance of IpcUI, DI gives me the service, but without any HttpContext or ActionContext... Sorry for the lack of information from my last edit :-). Hope it is a bit more specific.
Oh ! I forgot something, IpcUI is created at runtime not with a new (because that don't work) but with a custom extension function that retrieves the IServiceProvider for DI:
In startup
ExtensionsUtils.ServiceProvider = app.ApplicationServices;
In ExtensionsUtils
/// <summary>
/// This is called in configure services to get the collection of services in an extension static class
/// </summary>
public static IServiceProvider ServiceProvider { get; set; }
/// <summary>
/// Create a reference from type T with DI
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="o"></param>
/// <returns></returns>
public static T CreateAndResolveInstanceFromGeneric<T>(this T o)
{
return (T)ActivatorUtilities.CreateInstance<T>(ServiceProvider);
}
Edit 2:
I have tried to access IRazorViewToStringService from a real controller constructor and it's null again... What Am I doing wrong ???
private readonly IRazorViewToStringService _razorViewRenderService;
public BaseController(IRazorViewToStringService razorViewRenderService)
{
_razorViewRenderService = razorViewRenderService;
}
...
/// <summary>
/// Return a success http code and a View rendered as string
/// </summary>
/// <param name="ViewName">Name of MVC View (or PartialView)</param>
/// <param name="Model">Model to pass if any</param>
/// <returns>JSON: { result: "type", description: "Html Code" }</returns>
public async Task<ActionResult> CheckAndReturnView(string ViewName, object Model = null)
{
return Ok(await _razorViewRenderService.RenderViewToStringAsync(ViewName, Model));
}

C# Ninject Web API async query in IAuthenticationFilter causes multiple operations error in entity framework

I'm using Web API 2 with Ninject and i'm getting the following error when i've got multiple parallel HTTP calls.
A second operation started on this context before a previous asynchronous operation completed. Use 'await' to ensure that any asynchronous operations have completed before calling another method on this context. Any instance members are not guaranteed to be thread safe.
I didn't get this error before, all the code that retrieves the data from the database is async so i'm thinking its a Ninject scope issue.
NinjectWebCommon
kernel.BindHttpFilter<MyAuthenticateFilter>(FilterScope.Action);
// Database context
kernel.Bind<IUnitOfWorkAsyncFactory>().To<UnitOfWorkAsyncFactory>().InRequestScope();
kernel.Bind<IUnitOfWorkAsync>().To<UnitOfWork>().InRequestScope();
kernel.Bind<IDataFactory>().To<DataFactory>().InRequestScope();
All the Application and domain handlers are also async and make use of the same DataFactory and UnitOfWorkAsyncFactory.
Seems like there's a threading issue with the IAuthenticationFilter.
The factory pattern used for the DbContext.
public class DataFactory : Disposable, IDataFactory
{
private MyContext DbContext { get; set; }
public IDataContextAsync GetDataContext()
{
return DbContext ?? (DbContext = new MyContext());
}
public void AfterDispose()
{
DbContext = null;
}
public DataFactory()
{
}
public DataFactory(MyContext context)
{
DbContext = context;
}
}
I remember some time ago having issues with filter injection in WebApi and scopes being lost.
As far as I remember using this implementation of IDependencyResolver (can not remember where I got it) made the issue go away.
using System.Web.Http.Dependencies;
using global::Ninject.Syntax;
public class DependencyResolverWebApiNinject : DependencyScopeWebApiNinject, IDependencyResolver
{
public DependencyResolverWebApiNinject(IResolutionRoot resolutionRoot)
: base(resolutionRoot)
{
}
public virtual IDependencyScope BeginScope()
{
return this;
}
}
Where DependencyScopeWebApiNinject is :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http.Dependencies;
using global::Ninject;
using global::Ninject.Infrastructure.Disposal;
using global::Ninject.Parameters;
using global::Ninject.Syntax;
public class DependencyScopeWebApiNinject : DisposableObject, IDependencyScope
{
/// <summary>
/// Initializes a new instance of the <see cref="DependencyScopeWebApiNinject"/> class.
/// </summary>
/// <param name="resolutionRoot">The resolution root.</param>
public DependencyScopeWebApiNinject(IResolutionRoot resolutionRoot)
{
this.ResolutionRoot = resolutionRoot;
}
/// <summary>
/// Gets the resolution root.
/// </summary>
/// <value>The resolution root.</value>
protected IResolutionRoot ResolutionRoot
{
get;
private set;
}
/// <summary>
/// Gets the service of the specified type.
/// </summary>
/// <param name="serviceType">The type of the service.</param>
/// <returns>The service instance or <see langword="null"/> if none is configured.</returns>
public object GetService(Type serviceType)
{
var request = this.ResolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true);
return this.ResolutionRoot.Resolve(request).SingleOrDefault();
}
/// <summary>
/// Gets the services of the specifies type.
/// </summary>
/// <param name="serviceType">The type of the service.</param>
/// <returns>All service instances or an empty enumerable if none is configured.</returns>
public IEnumerable<object> GetServices(Type serviceType)
{
return this.ResolutionRoot.GetAll(serviceType).ToList();
}
}
hope this will help

Best way to prevent "using" from using a specific constructor from a framework class

I've got a wpf application and use the EF4 to communicate with a database.
I'm choosing the connectionstring dynamically, dependent on if a debugger is attach or not:
public static string CustomerConnectionString;
public static string ProjectsConnectionString;
private static void GetConnectionstring()
{
if (Debugger.IsAttached)
{
CustomerConnectionString = ConfigurationManager.ConnectionStrings["kundenEntities"].ConnectionString;
ProjectsConnectionString = ConfigurationManager.ConnectionStrings["projekteEntities"].ConnectionString;
}
else
{
CustomerConnectionString = ConfigurationManager.ConnectionStrings["kundenEntitiesRelease"].ConnectionString;
ProjectsConnectionString = ConfigurationManager.ConnectionStrings["projekteEntitiesRelease"].ConnectionString;
}
}
I'm doing this, to ensure not to accidently do stuff in the productive database.
An entity object is created on that way then:
using (ProjectEntities proj = new ProjectEntities(App.ProjectsConnectionString))
{
I'm proper code
}
Now I want to ensure, that I'm not accidently calling the default constructor to get the entity object.
That would cause that the entity object would use the default connectionstring from the app.config. The default connectionstring is the debug one, which connects to my local database.
Should be clear, that if that happens, the data that is getting queried from that entity
is working in my debugger, but wouldn't work for the user, because that user hasn't got an connection to my local database (-:
I did a workaround for now and derived the entity class and provide just the constructor that requires the connectionstring:
public class ProjectEntities : projekteEntities
{
public ProjectEntities(string connectionString) : base (connectionString){}
}
Update
I solve dit to my needs on that way:
I renamed the generted projekteEntitites class...
public partial class ObsoleteProjekteEntities : ObjectContext
{
#region Konstruktoren
/// <summary>
/// Initialisiert ein neues projekteEntities-Objekt mithilfe der in Abschnitt 'projekteEntities' der Anwendungskonfigurationsdatei gefundenen Verbindungszeichenfolge.
/// </summary>
public ObsoleteProjekteEntities() : base("name=projekteEntities", "projekteEntities")
{
this.ContextOptions.LazyLoadingEnabled = true;
OnContextCreated();
}
/// <summary>
/// Initialisiert ein neues projekteEntities-Objekt.
/// </summary>
public ObsoleteProjekteEntities(string connectionString) : base(connectionString, "projekteEntities")
{
this.ContextOptions.LazyLoadingEnabled = true;
OnContextCreated();
}
/// <summary>
/// Initialisiert ein neues projekteEntities-Objekt.
/// </summary>
public ObsoleteProjekteEntities(EntityConnection connection) : base(connection, "projekteEntities")
{
this.ContextOptions.LazyLoadingEnabled = true;
OnContextCreated();
}
and derived that class...
public class ProjectEntities : ObsoleteProjekteEntities
{
public ProjectEntities(string connectionString) : base (connectionString){}
}
...now I won't accidently call the original generated context with the default constructor.
Thanks for the other suggestions, will have a look at them too (-:
If you're already managing both release and debug connection string in your code, then comment out connection string in the web.config file. Even better, use .config file transformation tool to do this. Take a look at this tutorial.
Secondly, don't rely on coders to take care which connection string is used each time. Don't use Debugger.IsAttached to decide between debug and release mode. If someone runs the application without debugger, it will hit release database. Instead use C# pre-processor directives.
For example:
Go to Project properties
Go to Build tab
Check Define DEBUG constant
Go to file where you're setting the connection string and use following code:
#if DEBUG
CustomerConnectionString = ConfigurationManager.ConnectionStrings["kundenEntities"].ConnectionString;
ProjectsConnectionString = ConfigurationManager.ConnectionStrings["projekteEntities"].ConnectionString;
#else
CustomerConnectionString = ConfigurationManager.ConnectionStrings["kundenEntitiesRelease"].ConnectionString;
ProjectsConnectionString = ConfigurationManager.ConnectionStrings["projekteEntitiesRelease"].ConnectionString;
#endif

EF Code First MigrateDatabaseToLatestVersion accepts connection string Name from config

While trying to implement EF Migrations in my project I am stuck at one place.
EF Code First MigrateDatabaseToLatestVersion accepts connection string Name from config.
In my case database name get known at Runtime (User selects it from dropdown).
Just the way DbContext either accepts, ConnectionString or connectionString Name in it's constructor, "MigrateDatabaseToLatestVersion" does not accept the same
System.Data.Entity.Database.SetInitializer
(new MigrateDatabaseToLatestVersion<SrcDbContext, SRC.DomainModel.ORMapping.Migrations.Configuration>(connString));
Is there any other way to achieve this?
Thank you all. I did checkout the EF code from codeplex, and inherited my own class after understanding their source code. Here is the solution which I opted :-
public class MigrateDbToLatestInitializerConnString<TContext, TMigrationsConfiguration> : IDatabaseInitializer<TContext>
where TContext : DbContext
where TMigrationsConfiguration : DbMigrationsConfiguration<TContext>, new()
{
private readonly DbMigrationsConfiguration config;
/// <summary>
/// Initializes a new instance of the MigrateDatabaseToLatestVersion class.
/// </summary>
public MigrateDbToLatestInitializerConnString()
{
config = new TMigrationsConfiguration();
}
/// <summary>
/// Initializes a new instance of the MigrateDatabaseToLatestVersion class that will
/// use a specific connection string from the configuration file to connect to
/// the database to perform the migration.
/// </summary>
/// <param name="connectionString"> connection string to use for migration. </param>
public MigrateDbToLatestInitializerConnString(string connectionString)
{
config = new TMigrationsConfiguration
{
TargetDatabase = new DbConnectionInfo(connectionString, "System.Data.SqlClient")
};
}
public void InitializeDatabase(TContext context)
{
if (context == null)
{
throw new ArgumentException("Context passed to InitializeDatabase can not be null");
}
var migrator = new DbMigrator(config);
migrator.Update();
}
}
public static class DatabaseHelper
{
/// <summary>
/// This method will create data base for given parameters supplied by caller.
/// </summary>
/// <param name="serverName">Name of the server where database has to be created</param>
/// <param name="databaseName">Name of database</param>
/// <param name="userName">SQL user name</param>
/// <param name="password">SQL password</param>
/// <returns>void</returns>
public static bool CreateDb(string serverName, string databaseName, string userName, string password)
{
bool integratedSecurity = !(!string.IsNullOrEmpty(userName) || !string.IsNullOrEmpty(password));
var builder = new System.Data.SqlClient.SqlConnectionStringBuilder
{
DataSource = serverName,
UserID = userName,
Password = password,
InitialCatalog = databaseName,
IntegratedSecurity = integratedSecurity,
};
var db = new SrcDbContext(builder.ConnectionString);
var dbInitializer = new MigrateDbToLatestInitializerConnString<SrcDbContext, SRC.DomainModel.ORMapping.Migrations.Configuration>(builder.ConnectionString);
//following uses strategy to "CreateIfNotExist<>"
dbInitializer.InitializeDatabase(db);
return true;
}
}
You can make the MigrateDatabaseToLatestVersion initializer to use the connection string that was used by the context that triggered the migration in the first place.
This is done by passing useSuppliedContext: true to the MigrateDatabaseToLatestVersion constructor as described in the docs. In your case:
Database.SetInitializer(new MigrateDatabaseToLatestVersion<SrcDbContext, SRC.DomainModel.ORMapping.Migrations.Configuration>(useSuppliedContext: true));
What context is this running under? Website or Desktop App?
Under website, doing that is not a good idea. The database initializing strategy set against the type of context. So different connection strings with same type of context will override each other's init strategy.
If Desktop App, maybe include an extra utility to switch between database?
Either way I don't recommend doing this, but if you really want to do what you mentioned, it looks like you have to hack it.
using (var context = new DbContext("<Your connection string right in here>"))
{
var constructors = typeof (DbMigrator).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic);
var hackedDbMigrator = constructors[0].Invoke(new object[] { new Configuration(), context }) as DbMigrator;
hackedDbMigrator.Update();
}
The is a issue with Migrations call the DbContext dervied class with parameter. Once this is solved it should work. see here for a sample solution.
EntityFramework code-first custom connection string and migrations

Categories