我每天都会阅读几次CSV文件。它大约300MB,每次我必须阅读它,与数据库中的现有数据进行比较,添加新数据,隐藏旧数据并更新现有数据。还有大量数据无法触及。
我可以访问所有新旧文件,我想将新文件与之前的文件进行比较,只需更新文件中的更改内容即可。我不知道该怎么做,我用C#来完成我的所有工作。可能最有问题的一件事是,前一字段中的一行可能位于第二个Feed中的另一个位置,即使它根本没有更新。如果可能的话,我也想避免这个问题。
任何想法都会有所帮助。
答案 0 :(得分:2)
Equals
和GetHashCode
List<T>
或HashSet<T>
,第一步是在没有内容的情况下初始化它们。 if(inMemoryCollection.Contains(currentRowObject))
我猜你有一个Windows服务定期从文件位置读取CSV文件。每次阅读新的CSV文件时,您都可以重复上述过程。这样,您将能够维护以前插入的对象的内存中集合并忽略它们,而不管它们在CSV文件中的位置。
如果您拥有为您的数据定义的主键,那么您可以使用Dictionary<T,T>
,其中Key可以是唯一字段。这有助于您获得更多性能以进行比较,您可以忽略Equals
和GetHashCode
实施。
作为此过程的备份,您的数据库写入例程/存储过程应该以它首先检查的方式定义,如果表中已经存在记录,那么更新表,否则INSERT新记录。这将是UPSERT
。
请记住,如果您最终维护内存中的集合,请定期清除它,否则可能会导致内存不足异常。
答案 1 :(得分:0)
csv文件有多大?如果它的小试试以下
string [] File1Lines = File.ReadAllLines(pathOfFileA);
string [] File2Lines = File.ReadAllLines(pathOfFileB);
List<string> NewLines = new List<string>();
for (int lineNum = 0; lineNo < File1Lines.Length; lineNo++)
{
if(!String.IsNullOrEmpty(File1Lines[lineNum])
String.IsNullOrEmpty(File2Lines[lineNo]))
{
if(String.Compare(File1Lines[lineNo], File2Lines[lineNo]) != 0)
NewLines.Add(File2Lines[lineNo]) ;
}
else if (!String.IsNullOrEmpty(File1Lines[lineNo]))
{
}
else
{
NewLines.Add(File2Lines[lineNo]);
}
}
if (NewLines.Count > 0)
{
File.WriteAllLines(newfilepath, NewLines);
}
答案 2 :(得分:0)
好奇,你为什么要把旧文件与新文件进行比较?是不是SQL Server中旧文件的数据已经存在? (当你说数据库时,你的意思是SQL服务器吗?我假设是SQL服务器,因为你使用的是C#.net)
我的方法很简单:
使用存储过程来插入,更新和设置非活动文件
public static void ProcessCSV(FileInfo file)
{
foreach (string line in ReturnLines(file))
{
//break the lines up and parse the values into parameters
using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand command = conn.CreateCommand())
{
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "[dbo].sp_InsertToStaging";
//some value from the string Line, you need to parse this from the string
command.Parameters.Add("@id", SqlDbType.BigInt).Value = line["id"];
command.Parameters.Add("@SomethingElse", SqlDbType.VarChar).Value = line["something_else"];
//execute
if (conn.State != ConnectionState.Open)
conn.Open();
try
{
command.ExecuteNonQuery();
}
catch (SqlException exc)
{
//throw or do something
}
}
}
}
public static IEnumerable<string> ReturnLines(FileInfo file)
{
using (FileStream stream = File.Open(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
using (StreamReader reader = new StreamReader(stream))
{
string line;
while ((line = reader.ReadLine()) != null)
{
yield return line;
}
}
}
现在您编写存储过程以插入,更新,根据ID设置非活动字段。如果特定Id的Field_x(main_table)!= Field_x(staging_table),您将知道是否更新了一行,等等。
以下是检测主表和登台表之间的更改和更新的方法。
/* SECTION: SET INACTIVE */
UPDATE main_table
SET IsActiveTag = 0
WHERE unique_identifier IN
(
SELECT a.unique_identifier
FROM main_table AS a INNER JOIN staging_table AS b
--inner join because you only want existing records
ON a.unique_identifier = b.unique_identifier
--detect any updates
WHERE a.field1 <> b.field2
OR a.field2 <> b.field2
OR a.field3 <> b.field3
--etc
)
/* SECTION: INSERT UPDATED AND NEW */
INSERT INTO main_table
SELECT *
FROM staging_table AS b
LEFT JOIN
(SELECT *
FROM main_table
--only get active records
WHERE IsActiveTag = 1) AS a
ON b.unique_identifier = a.unique_identifier
--select only records available in staging table
WHERE a.unique_identifier IS NULL