C# 使用LINQ和C查询Microsoft Access MDB数据库
我有一个*.MDB数据库文件,我想知道是否有可能或建议使用C中的LINQ来处理它。我还想知道一些简单的示例会是什么样子C# 使用LINQ和C查询Microsoft Access MDB数据库,c#,linq,ms-access,C#,Linq,Ms Access,我有一个*.MDB数据库文件,我想知道是否有可能或建议使用C中的LINQ来处理它。我还想知道一些简单的示例会是什么样子 我对LINQ了解不多,但我相信我对这项任务的要求非常简单。用户将向我传递Microsoft Access MDB数据库的文件路径,我希望使用LINQ向数据库中的一个表添加行。您需要的是LINQ到ODBC提供程序或LINQ到JET/OLEDB提供程序 开箱即用,MS不做。可能有第三方这样做。LINQ to SQL仅适用于SQL Server数据库。您需要的是Microsoft实体
我对LINQ了解不多,但我相信我对这项任务的要求非常简单。用户将向我传递Microsoft Access MDB数据库的文件路径,我希望使用LINQ向数据库中的一个表添加行。您需要的是LINQ到ODBC提供程序或LINQ到JET/OLEDB提供程序
开箱即用,MS不做。可能有第三方这样做。LINQ to SQL仅适用于SQL Server数据库。您需要的是Microsoft实体框架。这使得对mdb的面向对象访问成为可能。从这里可以运行LINQ查询
事实上,我最近发现可以使用LinqToSql访问access数据库。它必须是2002或更新的格式,您将无法将表拖放到datacontext中,因此您可以在dbml中手动创建对象,也可以使用SQL Server Migration for Access将其移动到SQL Server,然后拖放所有需要的内容。当您想要实际创建上下文时,请向其传递OleDbConnection。在OLEDB连接上使用您的标准Jet.OLEDB.4.0连接字符串,就可以开始了。但我不确定这可能会带来什么限制。我只是做了一个快速的示例,并没有问题地完成了一个OrderBy。您可以使用数据集。有一些linq扩展,允许您使用我们所使用的所有linq功能来查询数据:
eICATDataSet.ICSWSbuDataTable tbl = new eICATDataSet.ICSWSbuDataTable();
ICSWSbuTableAdapter ta = new ICSWSbuTableAdapter();
ta.Fill(tbl);
var res = tbl.Select(x => x.ProcedureDate.Year == 2010);
我编写了一个小样本程序,用David的答案来测试这一点。您需要创建一个access数据库并手动为Linq to SQL创建DBML,因为您不能拖放它们 插入失败,引用缺少的分号;在SQL语句的末尾。但是查询似乎可以正常工作
using System;
using System.Collections.Generic;
using System.Data.OleDb;
using System.IO;
using System.Linq;
using Linq2Access.Data;
namespace Linq2Access
{
class Program
{
static readonly string AppPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
static readonly string DbPath = Path.Combine(AppPath, "Data", "database.accdb");
static readonly string DbConnString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" + DbPath + "';Persist Security Info=False;";
static void Main(string[] args)
{
if (!File.Exists(DbPath))
throw new Exception("Database file does not exist!");
using (OleDbConnection connection = new OleDbConnection(DbConnString))
using (DataRepositoryDataContext db = new DataRepositoryDataContext(connection))
{
List<dbProject> projects = new List<dbProject>();
for (int i = 1; i <= 10; i++)
{
dbProject p = new dbProject() { Title = "Project #" + i };
for (int j = 1; j <= 10; j++)
{
dbTask t = new dbTask() { Title = "Task #" + (i * j) };
p.dbTasks.Add(t);
}
projects.Add(p);
}
try
{
//This will fail to submit
db.dbProjects.InsertAllOnSubmit(projects);
db.SubmitChanges();
Console.WriteLine("Write succeeded! {0} projects, {1} tasks inserted",
projects.Count,
projects.Sum(x => x.dbTasks.Count));
}
catch(Exception ex)
{
Console.WriteLine("Write FAILED. Details:");
Console.WriteLine(ex);
Console.WriteLine();
}
try
{
//However, if you create the items manually in Access they seem to query fine
var projectsFromDb = db.dbProjects.Where(x => x.Title.Contains("#1"))
.OrderBy(x => x.ProjectID)
.ToList();
Console.WriteLine("Query succeeded! {0} Projects, {1} Tasks",
projectsFromDb.Count,
projectsFromDb.Sum(x => x.dbTasks.Count));
}
catch (Exception ex)
{
Console.WriteLine("Query FAILED. Details:");
Console.WriteLine(ex);
Console.WriteLine();
}
Console.WriteLine();
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
}
}
}
我在好几个论坛上多次看到这个问题。我尝试了一下,这里有一个完整的答案,供那些一直在看它的人参考 LinQ不是为访问而制作的。但是,许多查询都可以使用Access,包括删除过程。因此,据我所知,在使用Access时,只有两个关键缺陷,即: 无法保存数据。 无法将对象拖放到dbml上 插入将失败,错误为缺少分号;。这是因为LinQ保存过程用于保存数据并检索一次性保存的记录的主键ID。我们知道您无法在Access中执行多个SQL语句,因此这就是失败的原因 更新将失败,找不到错误记录。更新过程将查找要更新的记录,然后更新它。我说不出它为什么找不到它,当正常的LinQ查询可以找到记录时 因为使用LinQ有很多好处,所以我知道了如何克服这个缺陷,同时在整个应用程序中享受其他好处。以下是VB.net中的NB:My代码,但如果需要,您可以转换: 创建linqtosql.dbml类,以根据access数据库管理LinQ,以及管理保存过程的方法。以下是我创建的内容的完整过程,我现在与LinQ合作,以无任何问题地访问: 在窗体上添加DataGridView。添加、编辑和删除按钮 填充网格的代码: 详细表格 用于设置控制值的代码 私人转介表格
Try
If _accountTypeID = 0 Then
Exit Sub
End If
Using db As New AccessDataClassesDataContext(ACCCon)
'Dim rows = (From row In db.AccountTypes
' Where row.AccountTypeID = _accountTypeID
' Order By row.AccountTypeID Ascending
' Select row.AccountTypeID, row.AccountType, row.LastUpdated).ToList()
Dim rows = (From row In db.AccountTypes
Where row.AccountTypeID = _accountTypeID
Select row).ToList()
For Each s In rows
Me.AccountTypeIDTextBox.Text = s.AccountTypeID
Me.myGuidTextBox.Text = s.myGuid
Me.AccountTypeTextBox.Text = s.AccountType
Me.AcHeadIDTextBox.Text = s.AcHeadID
Me.DescriptionTextBox.Text = s.Description
Me.LastUpdatedDateTimePicker.Value = s.LastUpdated
Next
End Using
Catch ex As Exception
End Try
End Sub
LinQToSQLClass
由于使用Access时不能拖放,因此必须手动将数据对象添加到dbml中。还请注意,您必须在“属性”窗口中正确设置字段的所有属性。添加字段时未设置多个属性
要保存的代码
公共函数SaveAccountTypeOptional ByVal类型为字符串=
接近布尔值
Dim success As Boolean = False
Dim row As New AccountType
Using db As New AccessDataClassesDataContext(ACCCon)
If _accountTypeID > 0 Then
row = (From r In db.AccountTypes
Where r.AccountTypeID = _accountTypeID).ToList()(0)
If String.IsNullOrEmpty(row.AccountTypeID) Then
MessageBox.Show("Requested record not found", "Update Customer Error")
Return success
End If
End If
Try
With row
.myGuid = Me.myGuidTextBox.Text
.AccountType = Me.AccountTypeTextBox.Text
.Description = Me.DescriptionTextBox.Text
.AcHeadID = Me.AcHeadIDTextBox.Text
.LastUpdated = Date.Parse(Date.Now())
End With
If _accountTypeID = 0 Then db.AccountTypes.InsertOnSubmit(row)
db.SubmitChanges()
success = True
Catch ex As Exception
MessageBox.Show("Error saving to Customer: " & vbCr & ex.ToString, "Save Data Error")
End Try
End Using
Return success
End Function
现在替换这两行:
比如说:
现在您可以享受LinQ访问!快乐编码:你真的找到了一个与ACCESS合作的提供商吗?没有,我只是决定在没有LINQ to SQL的情况下用一种枯燥的方式来做。如何对MDB使用设计器?很抱歉,EF没有连接到MDB。当链接没有备份答案时,为什么会有UPVOUTS?提供答案的链接不适用于所问的问题。您所需要的是这样一个提供程序:不要忘记重命名designer.cs中没有所有者名称的tabletattributes,例如:将dbo.Articles重命名为ArticlesIt's跛脚充其量-尝试运行insert时,我丢失了分号;是的,我已经做过一次,您可以使用开箱即用的SELECT查询,但几乎所有其他内容都必须在代码中定义为命令。这是一个很大的工作,但仍然比手工完成要好。我知道这是一个老话题,但几年前我创建了一个像library这样的EntityFramework 这允许您使用LINQ直接访问MDB。它的功能还不完整,更新实体还不太受支持,但将表行作为对象检索效果很好
Dim success As Boolean = False
Dim row As New AccountType
Using db As New AccessDataClassesDataContext(ACCCon)
If _accountTypeID > 0 Then
row = (From r In db.AccountTypes
Where r.AccountTypeID = _accountTypeID).ToList()(0)
If String.IsNullOrEmpty(row.AccountTypeID) Then
MessageBox.Show("Requested record not found", "Update Customer Error")
Return success
End If
End If
Try
With row
.myGuid = Me.myGuidTextBox.Text
.AccountType = Me.AccountTypeTextBox.Text
.Description = Me.DescriptionTextBox.Text
.AcHeadID = Me.AcHeadIDTextBox.Text
.LastUpdated = Date.Parse(Date.Now())
End With
If _accountTypeID = 0 Then db.AccountTypes.InsertOnSubmit(row)
db.SubmitChanges()
success = True
Catch ex As Exception
MessageBox.Show("Error saving to Customer: " & vbCr & ex.ToString, "Save Data Error")
End Try
End Using
Return success
End Function
If _accountTypeID = 0 Then db.AccountTypes.InsertOnSubmit(row)
db.SubmitChanges()
Dim cmd As IDbCommand
cmd = Me.Connection.CreateCommand()
cmd.Transaction = Me.Transaction
cmd.CommandText = query
If myGuid.Trim.Length < 36 Then myGuid = UCase(System.Guid.NewGuid.ToString())
cmd.Parameters.Add(New OleDbParameter("myGuid", row.myGuid))
cmd.Parameters.Add(New OleDbParameter("AccountType", row.AccountType))
cmd.Parameters.Add(New OleDbParameter("Description", row.Description))
cmd.Parameters.Add(New OleDbParameter("AcHeadID", row.AcHeadID))
cmd.Parameters.Add(New OleDbParameter("LastUpdated", Date.Now))
If AccountTypeID > 0 Then cmd.Parameters.Add(New OleDbParameter("AccountTypeID", row.AccountTypeID))
If Connection.State = ConnectionState.Closed Then Connection.Open()
result = cmd.ExecuteNonQuery()
cmd = Me.Connection.CreateCommand()
cmd.Transaction = Me.Transaction
cmd.CommandText = "SELECT @@IDENTITY"
result = Convert.ToInt32(cmd.ExecuteScalar())
Private Sub DelButton_Click(sender As Object, e As EventArgs) Handles DelButton.Click
Using db As New AccessDataClassesDataContext(ACCCon)
Dim AccountTypeID As Integer = Me.DataGridView1.CurrentRow.Cells(0).Value
Dim row = From r In db.AccountTypes Where r.AccountTypeID = AccountTypeID
For Each detail In row
db.AccountTypes.DeleteOnSubmit(detail)
Next
Try
db.SubmitChanges()
Catch ex As Exception
' Provide for exceptions.
MsgBox(ex)
End Try
End Using
End Sub