Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用LINQ和C查询Microsoft Access MDB数据库_C#_Linq_Ms Access - Fatal编程技术网

C# 使用LINQ和C查询Microsoft Access MDB数据库

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实体

我有一个*.MDB数据库文件,我想知道是否有可能或建议使用C中的LINQ来处理它。我还想知道一些简单的示例会是什么样子


我对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