通过 streamreader 读取大的分号分隔文件并插入 sql db in vb.net
reading large semicolon separated files via streamreader and inserting in sql db in vb.net
我需要读取大型 csv 文件并将它们插入 SQL,我的想法是使用流读取器并逐行读取文件,因为如果我将内容存储在变量中,程序就会崩溃。这就是我的想法:
using FileStream fs
Dim list as String
Try
Dim MyFile as String = ("C:\Test.txt")
Using fs as FileStream = File.Open(MyFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None) 'file is opened in a protected mode
firstline= fs.ReadLine 'treat the firstline as columnname
rest = fs.ReadLine 'the rest as rest
Do While (Not rest Is Nothing) 'read the complete file
list.Add(rest)
Filestream.TextFieldType = FileIO.FieldType.Delimited
Filestream.SetDelimiters(";")
Loop
End Using
Catch
ResultBlock.Text = "File not readable"
End Try
我写了 list.Add(rest) 这实际上是个坏主意,因为当时内容存储在一个变量中,但我需要在 sql 数据库中读取并逐行插入不过似乎很复杂,有人知道我该如何处理吗?
如果因为文件太大而无法将文件读入内存,那么您需要的是某种缓冲区,用于将记录保存在内存中,并在列表达到一定大小时写入数据库。
如果您真的想让它易于管理,那么 reader、编写器和缓冲区都应该完全相互独立。这听起来像是更多的工作,因为它有更多的 classes,但它实际上更简单,因为每个 class 只做一件事。
我会创建一个 class 来表示您正在从文件中读取的项目,以及每条记录的属性。就像如果文件中的每一行代表一个有姓名和员工编号的人,创建一个 class like
public class Person
{
public string FirstName {get;set;}
public string LastName {get;set;}
public string EmployeeNumber {get;set;}
}
你需要一个缓冲区。缓冲区的工作是将项目放入其中,并在达到最大大小时刷新到写入器。大概是这样的:
public interface IBuffer<T>
{
void AddItem(T item);
}
public interface IWriter<T>
{
void Write(IEnumerable<T> items);
}
public class WriterBuffer<T> : IBuffer<T>
{
private readonly IWriter<T> _writer;
private readonly int _maxSize;
private readonly List<T> _buffer;
public WriterBuffer(IWriter<T> writer, int maxSize)
{
_writer = writer;
_maxSize - maxSize;
}
public void AddItem(T item)
{
_buffer.Add(item);
if(_buffer.Count >= _maxSize)
{
_writer.Write(_buffer);
_buffer.Clear();
}
}
}
那么,你的reader class根本不了解作者。它只知道它写入缓冲区。
public class PersonFileReader
{
private readonly string _filename;
private readonly IBuffer<Person> _buffer;
public PersonFileReader(string filename, IBuffer<Person> buffer)
{
_filename = filename;
_buffer = buffer;
}
public void ReadFile()
{
//Reads from file.
//Creates a new Person for each record
//Calls _buffer.Add(person) for each Person.
}
}
public class PersonSqlWriter : IWriter<Person>
{
private readonly string _connectionString;
public PersonSqlWriter(string connectionString)
{
_connectionString = connectionString;
}
public void Write(IEnumerable<Person> items)
{
//Writes the list of items to the database
//using _connectionString;
}
}
结果是每个 classes 只做一件事。您可以将它们与其他人分开使用,并与其他人分开测试。这适用于单一职责原则。没有人 class 太复杂,因为每个人都只有一项职责。它还应用了依赖倒置原则。 reader 不知道缓冲区的作用。这仅取决于界面。缓冲区不知道作者做了什么。而且作者不关心数据来自哪里。
现在复杂的是创建对象。您需要一个文件名、一个连接字符串和一个最大缓冲区大小。这意味着类似
var filename = "your file name";
var maxBufferSize = 50;
var connectionString = "your connection string"
var reader = new PersonFileReader(
filename,
new WriterBuffer<Person>(
new PersonSqlWriter(connectionString),
maxBufferSize));
您的 classes 更简单,但是将它们连接在一起变得有点复杂。这就是依赖注入的用武之地。它为您管理。我不会深入讨论,因为这可能是信息过载。但是如果你提到这是什么类型的应用程序——网络、WCF 服务等,那么我也许可以提供一个具体的例子来说明像 Windsor、Autofac 或 Unity 这样的依赖注入容器如何为你管理它。
几年前这对我来说是全新的。起初它看起来只是更多的代码。但它实际上使编写小而简单的 classes 变得更容易,这反过来又使构建复杂的应用程序变得更加容易。
查看以下链接:
批量复制 How can I insert 10 million records in the shortest time possible?
这包含代码示例:http://www.sqlteam.com/article/use-sqlbulkcopy-to-quickly-load-data-from-your-client-to-sql-server
您也可以使用导入向导 (https://msdn.microsoft.com/en-us/library/ms141209.aspx?f=255&MSPPError=-2147217396)。
我需要读取大型 csv 文件并将它们插入 SQL,我的想法是使用流读取器并逐行读取文件,因为如果我将内容存储在变量中,程序就会崩溃。这就是我的想法:
using FileStream fs
Dim list as String
Try
Dim MyFile as String = ("C:\Test.txt")
Using fs as FileStream = File.Open(MyFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None) 'file is opened in a protected mode
firstline= fs.ReadLine 'treat the firstline as columnname
rest = fs.ReadLine 'the rest as rest
Do While (Not rest Is Nothing) 'read the complete file
list.Add(rest)
Filestream.TextFieldType = FileIO.FieldType.Delimited
Filestream.SetDelimiters(";")
Loop
End Using
Catch
ResultBlock.Text = "File not readable"
End Try
我写了 list.Add(rest) 这实际上是个坏主意,因为当时内容存储在一个变量中,但我需要在 sql 数据库中读取并逐行插入不过似乎很复杂,有人知道我该如何处理吗?
如果因为文件太大而无法将文件读入内存,那么您需要的是某种缓冲区,用于将记录保存在内存中,并在列表达到一定大小时写入数据库。
如果您真的想让它易于管理,那么 reader、编写器和缓冲区都应该完全相互独立。这听起来像是更多的工作,因为它有更多的 classes,但它实际上更简单,因为每个 class 只做一件事。
我会创建一个 class 来表示您正在从文件中读取的项目,以及每条记录的属性。就像如果文件中的每一行代表一个有姓名和员工编号的人,创建一个 class like
public class Person
{
public string FirstName {get;set;}
public string LastName {get;set;}
public string EmployeeNumber {get;set;}
}
你需要一个缓冲区。缓冲区的工作是将项目放入其中,并在达到最大大小时刷新到写入器。大概是这样的:
public interface IBuffer<T>
{
void AddItem(T item);
}
public interface IWriter<T>
{
void Write(IEnumerable<T> items);
}
public class WriterBuffer<T> : IBuffer<T>
{
private readonly IWriter<T> _writer;
private readonly int _maxSize;
private readonly List<T> _buffer;
public WriterBuffer(IWriter<T> writer, int maxSize)
{
_writer = writer;
_maxSize - maxSize;
}
public void AddItem(T item)
{
_buffer.Add(item);
if(_buffer.Count >= _maxSize)
{
_writer.Write(_buffer);
_buffer.Clear();
}
}
}
那么,你的reader class根本不了解作者。它只知道它写入缓冲区。
public class PersonFileReader
{
private readonly string _filename;
private readonly IBuffer<Person> _buffer;
public PersonFileReader(string filename, IBuffer<Person> buffer)
{
_filename = filename;
_buffer = buffer;
}
public void ReadFile()
{
//Reads from file.
//Creates a new Person for each record
//Calls _buffer.Add(person) for each Person.
}
}
public class PersonSqlWriter : IWriter<Person>
{
private readonly string _connectionString;
public PersonSqlWriter(string connectionString)
{
_connectionString = connectionString;
}
public void Write(IEnumerable<Person> items)
{
//Writes the list of items to the database
//using _connectionString;
}
}
结果是每个 classes 只做一件事。您可以将它们与其他人分开使用,并与其他人分开测试。这适用于单一职责原则。没有人 class 太复杂,因为每个人都只有一项职责。它还应用了依赖倒置原则。 reader 不知道缓冲区的作用。这仅取决于界面。缓冲区不知道作者做了什么。而且作者不关心数据来自哪里。
现在复杂的是创建对象。您需要一个文件名、一个连接字符串和一个最大缓冲区大小。这意味着类似
var filename = "your file name";
var maxBufferSize = 50;
var connectionString = "your connection string"
var reader = new PersonFileReader(
filename,
new WriterBuffer<Person>(
new PersonSqlWriter(connectionString),
maxBufferSize));
您的 classes 更简单,但是将它们连接在一起变得有点复杂。这就是依赖注入的用武之地。它为您管理。我不会深入讨论,因为这可能是信息过载。但是如果你提到这是什么类型的应用程序——网络、WCF 服务等,那么我也许可以提供一个具体的例子来说明像 Windsor、Autofac 或 Unity 这样的依赖注入容器如何为你管理它。
几年前这对我来说是全新的。起初它看起来只是更多的代码。但它实际上使编写小而简单的 classes 变得更容易,这反过来又使构建复杂的应用程序变得更加容易。
查看以下链接:
批量复制 How can I insert 10 million records in the shortest time possible?
这包含代码示例:http://www.sqlteam.com/article/use-sqlbulkcopy-to-quickly-load-data-from-your-client-to-sql-server
您也可以使用导入向导 (https://msdn.microsoft.com/en-us/library/ms141209.aspx?f=255&MSPPError=-2147217396)。