0

I am developing a plug-in for Rhinoceros 6 and making editions to App.Config file of Rhinoceros seems impossible so far. App.Config of the plug-in project has no effect on App.Config of Rhinoceros.

Below error message appears because I couldn't add providers and parameters to App.Config's <entityFramework> section.

Unable to determine the provider name for provider factory of type 'System.Data.SqlServerCe.SqlCeProviderFactory'. Make sure that the ADO.NET provider is installed or registered in the application config.

I installed EntityFramework.SqlServer.Compact and Microsoft.SqlServer.Compact with NuGet and checked for references, all seems fine.

Below is my code-first dbcontext class :

    public class ModelLocalClipper : DbContext
    { 
        public ModelLocalClipper()
            : base(new SqlCeConnection("Data Source="+ Environment.GetFolderPath(Environment.SpecialFolder.Desktop)+"\\MyDatabase.sdf;Persist Security Info=False;"),
  contextOwnsConnection: true)
        {
            Database.SetInitializer<ModelLocalClipper>(new CreateDatabaseIfNotExists<ModelLocalClipper>());
        }
        
        public DbSet<Scene> Scenes { get; set; }
        public DbSet<LocalProject> LocalProjects { get; set; }
    }

    public class Scene
    {
        public int SceneId { get; set; }
        public string Name { get; set; }

        public int LocalProjectId { get; set; }

        [ForeignKey("LocalProjectId")]
        public virtual LocalProject LocalProject { get; set; }
    }

    public class LocalProject
    {
        public int LocalProjectId { get; set; }
        public string Name { get; set; }

        public virtual ICollection<Scene> Scenes { get; set; }
    }

After searching a while I found this solution and transformed that to use for SQL Server CE as below but it didn't help either

public class SqlCeProviderInvariantName : IProviderInvariantName
{
    public static readonly SqlCeProviderInvariantName Instance = new SqlCeProviderInvariantName();

    private SqlCeProviderInvariantName() { }

    public const string ProviderName = "System.Data.SqlServerCe.4.0";

    public string Name { get { return ProviderName; } }
}

class SqlCeDbProviderFactoryResolver : IDbProviderFactoryResolver
{
    public static readonly SqlCeDbProviderFactoryResolver Instance = new SqlCeDbProviderFactoryResolver();

    private SqlCeDbProviderFactoryResolver() { }

    public DbProviderFactory ResolveProviderFactory(DbConnection connection)
    {
        if (connection is SqlCeConnection) 
            return SqlCeProviderFactory.Instance;

        if (connection is EntityConnection) 
            return EntityProviderFactory.Instance;

        return null;
    }
}

class SqlCeDbDependencyResolver : IDbDependencyResolver
{
        public object GetService(Type type, object key)
        {
            if (type == typeof(IProviderInvariantName)) 
                return SqlCeProviderInvariantName.Instance;

            if (type == typeof(DbProviderFactory)) 
                return SqlCeProviderFactory.Instance;

            if (type == typeof(IDbProviderFactoryResolver)) 
                return SqlCeDbProviderFactoryResolver.Instance;

            return SqlCeProviderServices.Instance.GetService(type);
        }

        public IEnumerable<object> GetServices(Type type, object key)
        {
            var service = GetService(type, key);
            if (service != null) yield return service;
        }
    }

    class SqlCeDbConfiguration : DbConfiguration
    {
        public SqlCeDbConfiguration()
        {
            AddDependencyResolver(new SqlCeDbDependencyResolver());
        }
    }

Versions :

  • RhinoCommon 6.30.20288.16410
  • .NET Framework 4.8
  • Entity Framework 6.4.4
  • SQL Server CE 4.0

With directives of ErikEJ, it worked! For those who want to look into the code here is the repo: https://github.com/Tahirhan/RhinoPluginSqlCECodeFirst

Thanks!

8
  • Is the code in the resolver classes called? Is the SQL CE runtime MSI installed on the machine? Commented Jan 13, 2021 at 14:03
  • learn.microsoft.com/en-us/dotnet/api/… Commented Jan 13, 2021 at 14:05
  • learn.microsoft.com/en-us/dotnet/api/… Commented Jan 13, 2021 at 14:06
  • Hi @ErikEJ, I added DbConfiguration derived class that calls resolver to the code but the error persists. And yes SQL CE runtime installed (from this link microsoft.com/tr-tr/download/details.aspx?id=30709, I guess it is the right package to install?). Commented Jan 13, 2021 at 15:26
  • Yes, right package. Commented Jan 13, 2021 at 16:00

2 Answers 2

1

Try this (much simpler) approach, I was able to make that work with a Console app:

public class SqlCeDbConfiguration : DbConfiguration 
{
    public SqlCeDbConfiguration()
    {
        SetProviderServices(
            SqlCeProviderServices.ProviderInvariantName,
            SqlCeProviderServices.Instance);

        SetDefaultConnectionFactory(
            new SqlCeConnectionFactory(SqlCeProviderServices.ProviderInvariantName));
    }
}

And then:

[DbConfigurationType(typeof(SqlCeDbConfiguration))]
public class ModelSqlCECodeFirst : DbContext
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks a lot! I will edit the question and also update the repository. Using "Data Source=|DataDirectory|MyDatabase.sdf;Persist Security Info=False;" produced auth error (because rhino in program files ..) I made an additional change like this "Data Source=|DataDirectory|" + Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\MyDatabase.sdf;Persist Security Info=False;" and it worked.
As far as I understand, I need to install runtime for CE to run this project on the client's pc, I thought that I wouldn't need any external installations for CE.
If you use the standard package, you do. But you might be able to use my .PrivateDeployment package, if you can figure out how to register the DBProviderFactory in code.
0

As this answer suggested, For SQLite scenario try this DbConfiguration and don't forget to remove "|DataDirectory|" part from connection string

public class SQLiteConfiguration : DbConfiguration
{
    public SQLiteConfiguration()
    {
        SetProviderFactory("System.Data.SQLite", SQLiteFactory.Instance);
        SetProviderFactory("System.Data.SQLite.EF6", SQLiteProviderFactory.Instance);
        SetProviderServices("System.Data.SQLite", (DbProviderServices)SQLiteProviderFactory.Instance.GetService(typeof(DbProviderServices)));
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.