我有一个* .MDB数据库文件,我想知道是否有可能或建议在C#中使用LINQ来对抗它。我也想知道一些简单的例子会是什么样的。
我对LINQ知之甚少,但我对此任务的要求非常简单(我相信)。用户将传递给Microsoft Access MDB数据库的文件路径,我想使用LINQ将行添加到数据库中的一个表。
答案 0 :(得分:14)
您想要的是LINQ to ODBC提供程序,或LINQ to JET / OLEDB提供程序。
开箱即用,MS没有制作一个。可能有第三方。
答案 1 :(得分:13)
实际上我最近(今天)发现您可以使用LinqToSql访问Access数据库。它必须是2002或更新的格式,您将无法将表拖放到datacontext中,因此可以在dbml中手动创建对象,也可以使用SQL Server Migration for Access将其移动到sql server和然后拖放你想要的一切。当您想要实际创建上下文时,将其传递给OleDbConnection。在OleDbConnection上使用标准的Jet.OLEDB.4.0连接字符串,你很高兴。不确定这可能会产生的限制。我刚做了一个快速的样本并且没有问题就做了OrderBy。
答案 2 :(得分:7)
我写了一个小样本程序来测试大卫的回答。您需要创建一个访问数据库并手动创建Linq-to-SQL的DBML,因为您无法拖放它们。
插入失败,引用Missing semicolon (;) at end of SQL statement.
但查询似乎正常。
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();
}
}
}
}
答案 3 :(得分:1)
您可以使用DataSet。有linq扩展,允许您使用我们已经使用的所有LINQ优点来查询数据:)
eICATDataSet.ICSWSbuDataTable tbl = new eICATDataSet.ICSWSbuDataTable();
ICSWSbuTableAdapter ta = new ICSWSbuTableAdapter();
ta.Fill(tbl);
var res = tbl.Select(x => x.ProcedureDate.Year == 2010);
答案 4 :(得分:0)
LINQ to SQL仅适用于SQL Server数据库。您需要的是Microsoft实体框架。这使得面向对象访问您的mdb。从这里你可以运行LINQ查询。
http://msdn.microsoft.com/en-us/library/aa697427(vs.80).aspx
答案 5 :(得分:0)
我已经在很多论坛上看到了很多这个问题。我试了一下,对于那些一直在看它的人来说,这是一个完整的答案。
LinQ不是为Access做的。但是,许多查询将与Access一起使用,包括删除过程。因此,据我所知,使用Access时只有两个关键缺陷:
插入将失败并显示错误&#34;缺少分号(;)&#34;。这是因为LinQ保存程序用于保存数据并检索一次保存的记录的主键ID。我们知道您无法在Access中执行多个SQL语句,因此这就是失败的原因。
更新将失败并显示错误&#34;记录未找到&#34;。更新过程将导致查找要更新的记录然后更新它。我不知道为什么它找不到它,正常的LinQ查询找到一个记录工作正常。
因为使用LinQ有很多好处,所以我想出了如何解决这个问题,同时在整个应用程序中享受其他好处。这是如何(NB:我的代码在VB.net中,但您可以根据需要进行转换):
创建LinQ to SQL(.dbml)类以根据访问数据库管理LinQ,以及管理保存过程的方法。下面是我创建的完整程序,现在我正在使用LinQ to Access,没有任何问题:
在表单上添加DataGridView
。添加添加,编辑和按钮的按钮删除
填充网格的代码:
Private Sub ResetForm() Try Using db As New AccessDataClassesDataContext(ACCCon) Dim rows = (From row In db.AccountTypes Where row.AccountTypeID > 1 Order By row.AccountTypeID Ascending Select row).ToList() Me.DataGridView1.DataSource = rows End Using Catch ex As Exception MessageBox.Show("Error: " & vbCr & ex.ToString, "Data Error", MessageBoxButtons.OK) End Try End Sub
DetailForm
设置控制值的代码
Private Sub ResetForm()
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
您必须手动将数据对象添加到dbml,因为在使用Access时无法拖放。另请注意,您必须在属性窗口中正确设置字段的所有属性。添加字段时未设置多个属性。
保存代码
公共函数SaveAccountType(可选ByVal类型为String = &#34;关闭&#34;)作为布尔
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())
上面代码的最后一部分是获取保存记录的ID的原因。就个人而言,我通常会选择这个,因为在大多数情况下我都不需要它,因此我不需要在每次保存记录时添加取回数据的开销,我很高兴只知道保存了一条记录。
这是添加到LinQ的开销,导致Insert无法使用Access。拥有它真的有必要吗?我不这么认为。
您可能已经注意到我通常将我的更新和插入程序放在一起,这样可以节省我的时间并解决插入和插入问题。一次更新程序。
删除代码:
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
现在您可以享受LinQ访问!快乐的编码:)