c# - 在使用参数化查询插入之前检查 Foxpro 数据库中是否存在记录

标签 c# visual-foxpro

我创建了一个程序,可以从 Excel 电子表格中提取数据并将其推送到 FoxPro 数据库。但是,我遇到了出现重复客户记录的问题。

这是由于一个客户端与多个其他记录相关联。

我需要知道如何在写入之前检查数据库以查看特定记录是否存在,但我完全空白。

我的代码(针对这个特定的类)如下所示:

namespace PropertyImport
{
public class Landlord
{
    public void Import()
    {
        int IDCOUNT = 0;
        using (var exportConnection = new OleDbConnection(connectionString: Settings.ImportFrom))
        using (var importConnection = new OleDbConnection(connectionString: Settings.ImportTo))


        using (OleDbCommand exportCommand = new OleDbCommand(@"SELECT 
[clcodel salute],
[clcodel fname],
[clcodel sname]
from [export_test$]"
, exportConnection))
        using (OleDbCommand importCommand = new OleDbCommand(@"INSERT INTO CLIENT 
        (CLCODE,CLCODEDESC,CLCLASS,
        FNAME,MNAME,SNAME
        )
        VALUES 
        (?,?,?,?,?,?,?,?)",
                    importConnection))
        {
            OleDbDataReader exportReader;
            //

            importCommand.Parameters.AddWithValue("CLCODE", "");
            importCommand.Parameters.AddWithValue("CLCODEDESC", "");
            //importCommand.Parameters.AddWithValue("CLCLASS", "");
            //importCommand.Parameters.AddWithValue("NEGOTIATOR", "");
            //importCommand.Parameters.AddWithValue("TITLE", "");
            importCommand.Parameters.AddWithValue("FNAME", "");
            importCommand.Parameters.AddWithValue("MNAME", "");
            importCommand.Parameters.AddWithValue("SNAME", "");

            // Open connections to excel sheet and foxpro database
            exportConnection.Open();
            importConnection.Open();

            Console.WriteLine("Visual Foxpro connection open");
            Console.WriteLine("Writing to table");
            Console.WriteLine("...");

            int nLoopCount = 0;
            string space = " ";

            // Initiate the reader to excel
            exportReader = exportCommand.ExecuteReader();
            // Start reading
            while (exportReader != null && exportReader.Read())
            {

                //Set parameter values whilst reading from excel
                string LandTitle = exportReader.IsDBNull(0)
                    ? string.Empty
                    : Convert.ToString(exportReader.GetValue(0)).Trim();
                string LandFname = exportReader.IsDBNull(1)
                    ? string.Empty
                    : Convert.ToString(exportReader.GetValue(1)).Trim();
                string LandSname = exportReader.IsDBNull(2)
                    ? string.Empty
                    : Convert.ToString(exportReader.GetValue(2));
                string CLCODE = string.Concat(LandFname, space, LandSname, " (P)").Trim();
                Console.WriteLine("Working on record {0}, {1}", IDCOUNT, CLCODE);


                importCommand.Parameters["CLCODE"].Value = string.Concat(LandFname, space, LandSname, " (P)").Trim();
                importCommand.Parameters["CLCODEDESC"].Value = string.Concat(LandTitle, space, LandFname, space, LandSname).Trim();
                importCommand.Parameters["TITLE"].Value = LandTitle.Trim();
                importCommand.Parameters["FNAME"].Value = LandFname.Trim();
                importCommand.Parameters["SNAME"].Value = LandSname.Trim();

                try
                {
                    importCommand.ExecuteNonQuery();
                }
                catch (Exception e)
                {
                    Console.Write("Error Writing to database");
                    Console.Write(e);
                    Console.ReadKey();
                }

                // We must close and re-open the connection after a certain number of records or the OLEDB FoxPro SQL will eventually fail
                if (nLoopCount % 100 == 0)
                {
                    importConnection.Close();
                    importConnection.Open();
                }

            }

            // done
            exportConnection.Close();
            importConnection.Close();

            Console.WriteLine("Landlord Import Complete!");
            Console.WriteLine("Press any key to continue...");
            Console.ReadKey();
            if (Settings.ImportPropertyPause) Console.ReadKey();

        }
    }

}

}

我想做这样的事情:

if (CLCODE exists)
{
Do not not create record
}
else
{
create record
}

最佳答案

约书亚, 你让它变得不必要的复杂。在多用户环境中,您可能会遇到“如果不存在则检查并插入”逻辑的问题。如果您认为这不是问题,您可以执行 ExecuteScalar() 来检查该 clcode 的行数。如果为 0,则不存在。

如果您愿意这样做,那么更喜欢使用 Linq。对于 Linq,它只是:

bool exists = vfpdb.Clients.Any(c=>c.ClCode == "codetocheck");

查看它是否存在。

无论如何,有一种更简单的方法,这确实是一种技巧,但确实有效。假设您在“d:\backyard\temp”和“d:\temp\myclients.xlsx”文件下有 client.dbf(仅用于演示目的,这就是我选择的):

void Main()
{
    string vfpInsert = @"Insert Into client 
    (CLCODE,CLCODEDESC,CLCLASS,FNAME,MNAME,SNAME) 
    SELECT CLCODE,CLCODEDESC,CLCLASS,FNAME,MNAME,SNAME 
     from (Iif(Xmltocursor(?,'xlData') > 0, 'xlData','')) xl 
     where Not Exists
      (Select * From client c2 Where c2.CLCODE == xl.CLCODE)";

    var xml = GetExcelData();

    using (OleDbConnection con=new OleDbConnection(@"provider=VFPOLEDB;Data Source="+@"d:\backyard\temp"))
    using (OleDbCommand cmd = new OleDbCommand(vfpInsert,con))
    {
        cmd.Parameters.Add("xldata", OleDbType.VarChar).Value = xml;
        con.Open();
        cmd.ExecuteNonQuery();
        con.Close();
    }
}

private string GetExcelData()
{
    string dataSource = @"D:\temp\myclients.xlsx";
    DataTable t = new DataTable("Clients");

    using (OleDbConnection con = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;" +
      string.Format("Data Source={0};", dataSource) +
      "Extended Properties=\"Excel 12.0;HDR=Yes\""))
    using (OleDbCommand cmd = new OleDbCommand("Select * from [clients$]", con))
    {
        con.Open();
        t.Load(cmd.ExecuteReader());
        con.Close();
    }
    using (MemoryStream ms = new MemoryStream())
    using (var xmlwriter = XmlTextWriter.Create(ms))
    {
        t.WriteXml(xmlwriter, XmlWriteMode.WriteSchema);
        xmlwriter.Flush();
        xmlwriter.Close();
        ms.Position = 0;
        using (StreamReader streamreader = new StreamReader(ms))
        {
            return streamreader.ReadToEnd();
        }
    }
}

编辑:这是代码作用的解释:

  • 从 Excel 中获取数据作为 DataTable 并转换为 XML 字符串。
  • 将 XML 作为参数传递给 VFP 插入命令。
  • Insert 命令,将 XML 展开为游标(几乎总是在内存表中),然后选择那些不存在的内容(使用 ClCode)并将它们一次性插入到客户端表中。

关于c# - 在使用参数化查询插入之前检查 Foxpro 数据库中是否存在记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41815353/

相关文章:

c# - Console.ReadLine() 跳过第一个输入字符

javascript - RingCentral 调用管理

visual-studio - 如果切换到 Visual FoxPro,Microsoft Visual Studio Community 2015 总是在 Windows 10 中崩溃

c# - 基于 XPath 创建 XML 节点?

c# - 将 PDF 中的外部链接转换为链接到 iTextSharp 中的嵌入式附件

c# - 无法将 NULL 值插入自动增量主键列

mercurial - 带有 Mercurial 的 Visual FoxPro?

sql - 如何在 Microsoft Visual FoxPro 9 中执行自定义函数?

c# - 收到错误 "The ' VFPOLEDB。 1' provider is not registered on the local machine"即使在安装和注册提供商之后

foxpro - 查询中的数字溢出