【问题标题】:Entity Framework 6 SQL Server Compact 3.5 without Config file实体框架 6 SQL Server Compact 3.5 没有配置文件
【发布时间】:2016-02-09 09:22:41
【问题描述】:

我正在尝试使用 EntityFramework.SqlServerCompact.Legacy 6.1.3 使用实体框架 6 访问 SQL Server Compact 3.5 数据库。

我的应用程序是 Visual Studio 扩展,我无法向应用程序配置文件添加任何内容。

如果我做一个简单的测试应用程序,我可以毫无问题地连接到数据库。如果我尝试从类库访问数据库,则会失败并显示错误消息

指定的架构无效。错误: ProjectTemplate.ssdl(2,2):错误 0152:没有为具有不变名称“System.Data.SqlServerCe.3.5”的 ADO.NET 提供程序找到实体框架提供程序。确保提供程序已在应用程序配置文件的“entityFramework”部分注册。请参阅http://go.microsoft.com/fwlink/?LinkId=260882 了解更多信息。

我找到了一些有趣的链接,例如 herehere,但我无法让它工作,因为该示例适用于 EF5 或 SQL Server(或者我的眼睛有毛病)。

我该怎么做?

【问题讨论】:

  • 您无法做到这一点,您必须要求安装 SQL Server Compact 3.5 SP2 运行时。您最好的方法是在您的扩展程序启动时对此进行测试,并将您的用户指向 MSI 的下载位置。请记住,x86 和 x64 MSI 都必须安装在 x64 系统上。如果使用4.0,安装体验会好很多(单微星)
  • 这不是我的直接问题(但我意识到这是一个问题)。我的问题是我不知道如何在 app.config 中没有任何条目的情况下初始化实体框架上下文。
  • @ErikEJ 感谢您的回复,但我很难让它发挥作用。您提供的链接包含多个解决方案。最简单的看起来像标有“LATE ANSWER”的那个。我可以实例化 DbProviderFactory 并为数据库连接提供连接字符串,而无需 EF 元数据。我不知道如何使用连接和指定 EDMX 文件的元数据来创建 DbContext。我也尝试了接受的答案(来自 JoshRivers),但我也无法让它发挥作用。我还没有尝试过 IDbDependencyResolver 方法。

标签: c# .net entity-framework sql-server-ce app-config


【解决方案1】:

我目前正在使用控制台应用程序和类库进行测试。控制台应用程序对实体框架一无所知,只是调用类库中的方法。

static void Main(string[] args)
{
  EFTest t = new EFTest();
  t.Test();
}

这是类库中的代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Core.EntityClient;

namespace EF6_SQLCompact_CleanTest_000
{
  public class EFTest
  {
    public void Test()
    {
      try
      {
        // Add an event handler for DbConfiguration.Loaded, which adds our dependency 
        // resolver class to the chain of resolvers.
        System.Data.Entity.DbConfiguration.Loaded += (_, a) => {
          a.AddDependencyResolver(new MyDependencyResolver(), true);
        };

        // Define the provider connection string, specifying the SQL Server Compact 3.5 filename.
        String FileName = @"f:\DotNetTestProjects\2015\CS\SQLCompact35DllTest\SQLCompact35DllTest\ProjectTemplate.sdf";
        String ConnectionString = String.Format("Data Source={0}", FileName);

        // Create the entity framework connection string, specifying the model,
        // the provider and the provider connection string.
        var builder = new EntityConnectionStringBuilder();
        builder.Metadata = @"res://*/ProjectTemplate.csdl|res://*/ProjectTemplate.ssdl|res://*/ProjectTemplate.msl";
        builder.Provider = "System.Data.SqlServerCe.3.5";
        builder.ProviderConnectionString = ConnectionString;

        // Create the entity framework kontext
        Entities Context = new Entities(builder.ToString());

        // Do a trivial query as a test.
        int i = Context.Languages.Count();
        MessageBox.Show(i.ToString());
      }
      catch (Exception e)
      {
        MessageBox.Show(e.Message);
      }
    }
  }

  // Define an additional constructor for the Entities class, so that we can 
  // pass the connection string into the base class DbContext.
  public partial class Entities : DbContext
  {
    public Entities(String ConnectionString)
      : base(ConnectionString)
    {
    }
  }

  class MyDependencyResolver : System.Data.Entity.Infrastructure.DependencyResolution.IDbDependencyResolver
  {
    public object GetService(Type type, object key)
    {
      // Output the service attempting to be resolved along with it's key 
      System.Diagnostics.Debug.WriteLine(string.Format("MyDependencyResolver.GetService({0}, {1})", type.Name, key == null ? "" : key.ToString()));

      if ((type == typeof(System.Data.Common.DbProviderFactory))
           && (key != null)
           && ((string)(key) == "System.Data.SqlServerCe.3.5"))
      {
        return System.Data.SqlServerCe.SqlCeProviderFactory.Instance ;
      }
      else if ((type == typeof(System.Data.Entity.Core.Common.DbProviderServices))
                && (key != null)
                && ((string)(key) == "System.Data.SqlServerCe.3.5"))
      {
        return System.Data.Entity.SqlServerCompact.Legacy.SqlCeProviderServices.Instance ;
      }
      else if ((type == typeof(System.Data.Entity.Infrastructure.IProviderInvariantName))
                && (key is System.Data.SqlServerCe.SqlCeProviderFactory))
      {
        return new MyProviderInvariantName();
      }

      return null;
    }

    public IEnumerable<object> GetServices(Type type, object key)
    {
      return new object[] { GetService(type, key) }.ToList().Where(o => o != null);
    }
  }

  // Implement IProviderInvariantName so that we can return an object when
  // requested in GetService()
  class MyProviderInvariantName : IProviderInvariantName
  {
    public string Name
    {
      get { return "System.Data.SqlServerCe.3.5"; }
    }
  }
}

依赖解析器基于 Ryan Griffith 在 EricEJ 提到的链接中的回答。

这似乎在我的测试程序的上下文中工作,但我还没有在 Visual Studio 扩展的上下文中尝试过。

据我所知,只有在 DbConfiguration 首次在 AppDomain 中加载之前将事件处理程序添加到 DbConfiguration.Loaded 时(我可能无法保证),这种技术才有效。我还担心它可能会对 Visual Studio 或其他 Visual Studio 扩展产生副作用。

【讨论】:

  • 在 machine.config 中没有条目,在 GAC 中没有 3,5 文件?
  • 我确实正常安装了 SQL Server Compact 3.5。 machine.config 在 DbProviderFactories 中包含 4.0 和 3.5 的条目。不知道有没有被使用。 System.Data.SqlServerCe.dll 正在从 GAC 加载。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多