转载

c# 使用Entity Framework操作Access数据库

Entity Framework是C#开发中最常见的ORM工具。默认Entity Framework只提供支持MSSQL的 provider factory 。但是开发者开源贡献了对SQLite、MySql以及Access等的支持。

JetEntityFrameworkProvider

JetEntityFrameworkProvider为Access数据库文件兼容Entity Framework提供了相应的 Provider 。在nuget中直接搜索JetEntityFrameworkProvider即可安装该工具。虽然大多数操作最终是EntityFramework完成因此不需要什么变化,而在数据库连接等方面还是有些不同和需要注意的地方。

数据库连接

官方的资源并不多,只提供了一两个简单的 操作视频

其中使用的 connectionString 为在App.config中或Web.config中预定义的以供DbContext实例化时引用。

<connectionStrings>  
    <add name="DefaultConnection" connectionString="Provider=Microsoft.ACE.OleDb.12.0;Data Source=你的mdb或accdb文件绝对路径" providerName="JetEntityFrameworkProvider" />
</connectionStrings>

这样你在实例化自定义的 DbContext 子类时直接 base("name=DefaultConnection") 即可建立数据库连接。

但是我个人不喜欢在配置文件中写死配置,我更希望使用 base(existingConnection, contextOwnsConnection) 这种DbContext构造模式,所以需要先直接生成一个 DbConnection ,这里具体的就是 OleDbConnection 而不是 SqlConnection 了。

按照下面的方式直接使用 DbProviderFactory 创建连接:

var dbConnectionString = "Provider=Microsoft.ACE.OleDb.12.0;Data source=Access文件绝对路径;Persist Security Info=False";  
var conn = DbProviderFactories.GetFactory("JetEntityFrameworkProvider").CreateConnection();  
conn.ConnectionString = dbConnectionString;

Code First或DB First

默认地,JetEntityFrameworkProvider只支持code first模式。即你先写好模型,然后根据模型生成数据库。

但是我的需求是用EF读取已存在的Access数据库文件,即DB First模式,这时使用EF读取Access数据库文件会报错提示数据库已存在。

通过code first模式的测试发现:

JetEntityFrameworkProvider会创建一个名为 __MigrationHistory 的表,字段如下:

MigrationId - text格式  
ContextKey - memo格式  
Model - OleObject格式  
ProductVersion - text格式

MigrationId值的例子为 201612281720088_InitialCreate

ContextKey应该是自定义的DbContext类的namespace加类名的格式

Model是二进制的数据无法查看

ProductVersion包含了Entity Framework的版本号和JetEntityFrameworkProvider的版本号

因此我尝试在EF连接之前用普通SQL query方式插入记录:

var dbConnectionString = "Provider=Microsoft.ACE.OleDb.12.0;Data source=Access文件绝对路径;Persist Security Info=False";  
conn = new OleDbConnection(dbConnectionString);  
conn.Open();  
var exists = conn.GetSchema("Tables", new string[4] { null, null, "__MigrationHistory", "TABLE" }).Rows.Count > 0;

if(!exists)  
    {
         OleDbCommand cmd = new OleDbCommand("CREATE TABLE __MigrationHistory([MigrationId] TEXT, [ContextKey] MEMO, [Model] OleObject, [ProductVersion] TEXT)", conn);
          cmd.ExecuteNonQuery();

          cmd = new OleDbCommand("INSERT INTO __MigrationHistory(MigrationId, ContextKey, ProductVersion) VALUES('" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + "', '" + typeof(ATOrionContext).Namespace + ".ATOrionContext', '6.1.3-40302')", conn);
           cmd.ExecuteNonQuery();

    }

执行如上操作后确实能够利用EF连接已存在模型对应数据表的Access数据库文件了,但是执行查询操作仍然会报错 buffer is null

经过Debug发现此buffer指的就是插入记录的Model字段,我们插入时没有提供值,因为它是一个二进制数据,内容生成方式未知。

尝试注释掉插入记录的操作,只添加__MigrationHistory表,而结果也令人兴奋,可以通过模型验证并且能够使用EF进行DB First模式的数据开发模式了。

原文  http://www.fedepot.com/c-shi-yong-entity-frameworkcao-zuo-accessshu-ju-ku/
正文到此结束
Loading...