C# 将根目录和子目录导出到SQL Server数据库
我想知道是否有人知道如何将文件夹结构从文件系统导出到SQL Server数据库表中?我可以在树状视图中成功地创建结构,并考虑将结构导出到数据库中,但无法找到最好的方法,以便在数据库表中正确地表示它。基本上,我要做的是创建一个具有父/子关系的递归表结构。例如-C# 将根目录和子目录导出到SQL Server数据库,c#,sql-server,C#,Sql Server,我想知道是否有人知道如何将文件夹结构从文件系统导出到SQL Server数据库表中?我可以在树状视图中成功地创建结构,并考虑将结构导出到数据库中,但无法找到最好的方法,以便在数据库表中正确地表示它。基本上,我要做的是创建一个具有父/子关系的递归表结构。例如-ID、Name、Parentid、等 如果有人有想法或任何想法-提前感谢 编辑: 我可以用树状视图在UI上显示文件夹结构,没有问题,这不是问题所在。问题是获取该树结构并将其导出到数据库中(如上所述的父/子表示)。例如,我可以毫无问题地表示数据
ID、Name、Parentid、
等
如果有人有想法或任何想法-提前感谢
编辑:
我可以用树状视图在UI上显示文件夹结构,没有问题,这不是问题所在。问题是获取该树结构并将其导出到数据库中(如上所述的父/子表示)。例如,我可以毫无问题地表示数据库中的树结构,甚至可以表示文件系统中的树结构,它基本上是从文件系统中执行的,并将该结构导出/导入到数据库中。把它弄出来不是问题
希望这有意义。你刚刚做到了。这种结构有什么问题?您可能希望添加一个属性列,在该列中可以指定对象是文件还是目录,但如果只想记录目录结构,则每个对象(行)都是目录,而不需要属性列 你可以无限期地嵌套它 现在的问题是,您需要编写客户机代码,以获取嵌套结构并将其显示在UI中,或者使用它执行其他操作 要填充结构,.net为您提供了遍历要复制的文件系统所需的数据,您只需在数据库中为递归遍历目标文件系统时遇到的每个目录插入一行
更具体地说,创建一个名为“行走:需要两个参数。第一个是目录的名称,第二个是父目录的行id。在walk函数中,首先在表中插入一行,其中包含作为参数传入的目录名和父id。获取刚刚插入的行的行id;然后调用filesystem.getdirectories函数并将目录名传递给它。对于该函数返回的每个目录,通过传递子目录的名称和父目录的id回调函数(递归调用)。在main中,调用函数,将树的根的名称作为第一个参数传递给它,并将零作为第二个参数传递给它,这意味着在根级别没有父级,它将用树结构填充数据库。您刚刚这样做了。这种结构有什么问题?您可能希望添加一个属性列,在该列中可以指定对象是文件还是目录,但如果只想记录目录结构,则每个对象(行)都是目录,而不需要属性列 你可以无限期地嵌套它 现在的问题是,您需要编写客户机代码,以获取嵌套结构并将其显示在UI中,或者使用它执行其他操作 要填充结构,.net为您提供了遍历要复制的文件系统所需的数据,您只需在数据库中为递归遍历目标文件系统时遇到的每个目录插入一行
更具体地说,创建一个名为“行走:需要两个参数。第一个是目录的名称,第二个是父目录的行id。在walk函数中,首先在表中插入一行,其中包含作为参数传入的目录名和父id。获取刚刚插入的行的行id;然后调用filesystem.getdirectories函数并将目录名传递给它。对于该函数返回的每个目录,通过传递子目录的名称和父目录的id回调函数(递归调用)。在main中,调用函数,将树的根名称作为第一个参数传递给它,将零作为第二个参数传递给它,这意味着根级别没有父级,它将用树结构填充数据库。这是一个简单的树漫游。给出这样一张表:
create table dbo.directory
(
id int not null identity(1,1) primary key clustered ,
parent_id int null foreign key references dbo.directory( id ) ,
name varchar(256) collate SQL_Latin1_General_CP1_CI_AS not null , -- case-insensensitive, accent-sensitive
unique ( id , name ) ,
)
go
像这样的课应该对你有用
class DirectoryTreeLoader : IDisposable
{
const string connectionString = "Server=localhost;Database=sandbox;Trusted_Connection=True;" ;
private SqlConnection Connection ;
private SqlCommand Command ;
private bool CommandPrepared ;
private SqlParameter ParentDirectoryId ;
private SqlParameter DirectoryName ;
public DirectoryTreeLoader()
{
Connection = new SqlConnection(connectionString) ;
Command = Connection.CreateCommand() ;
ParentDirectoryId = new SqlParameter( "@parent_id" , SqlDbType.Int , 4 ) ;
DirectoryName = new SqlParameter( "@name" , SqlDbType.VarChar , 256 ) ;
ParentDirectoryId.IsNullable = true ;
DirectoryName.IsNullable = false ;
Command.Parameters.Add( ParentDirectoryId ) ;
Command.Parameters.Add( DirectoryName ) ;
Command.CommandType = CommandType.Text ;
Command.CommandText = @"
insert dbo.directory ( parent_id , name ) values ( @parent_id , @name ) ;
select id = scope_identity() ;
".Trim() ;
return ;
}
public void Load( DirectoryInfo root )
{
if ( Connection.State == ConnectionState.Closed )
{
Connection.Open() ;
Command.Prepare() ;
}
Visit( null , root ) ;
return ;
}
private void Visit( int? parentId , DirectoryInfo dir )
{
// insert the current directory
ParentDirectoryId.SqlValue = parentId.HasValue ? new SqlInt32( parentId.Value ) : SqlInt32.Null ;
DirectoryName.SqlValue = new SqlString( dir.Name ) ;
object o = Command.ExecuteScalar() ;
int id = (int)(decimal) o ;
// visit each subdirectory in turn
foreach ( DirectoryInfo subdir in dir.EnumerateDirectories() )
{
Visit(id,subdir) ;
}
return ;
}
public void Dispose()
{
if ( Command != null )
{
Command.Cancel();
Command.Dispose();
Command = null ;
}
if ( Connection != null )
{
Connection.Dispose() ;
Connection = null ;
}
return ;
}
}
用法
static void Main( string[] args )
{
DirectoryInfo root = new DirectoryInfo( @"c:\inetpub" ) ;
using ( DirectoryTreeLoader loader = new DirectoryTreeLoader() )
{
loader.Load(root) ;
}
return ;
}
如果要消除递归的Visit()
,只需使用堆栈:
public void Load( DirectoryInfo root )
{
if ( Connection.State == ConnectionState.Closed )
{
Connection.Open() ;
Command.Prepare() ;
}
Stack<Tuple<int?,DirectoryInfo>> pending = new Stack<Tuple<int?, DirectoryInfo>>();
pending.Push(new Tuple<int,DirectoryInfo>(null,root) ) ;
while ( pending.Count > 0 )
{
Tuple<int?,DirectoryInfo> dir = pending.Pop() ;
// insert the current directory
ParentDirectoryId.SqlValue = dir.Item1.HasValue ? new SqlInt32( dir.Item1.Value ) : SqlInt32.Null ;
DirectoryName.SqlValue = new SqlString( dir.Item2.Name ) ;
object o = Command.ExecuteScalar() ;
int parentId = (int)(decimal) o ;
// push each subdirectory onto the stack
foreach ( DirectoryInfo subdir in dir.Item2.EnumerateDirectories() )
{
pending.Push( new Tuple<int?, DirectoryInfo>(parentId,subdir));
}
}
return ;
}
公共无效加载(目录信息根目录)
{
if(Connection.State==ConnectionState.Closed)
{
Connection.Open();
Command.Prepare();
}
堆栈挂起=新堆栈();
Push(新元组(null,root));
同时(挂起。计数>0)
{
Tuple dir=pending.Pop();
//插入当前目录
ParentDirectoryId.SqlValue=dir.Item1.HasValue?新的SqlInt32(dir.Item1.Value):SqlInt32.Null;
DirectoryName.SqlValue=新的SqlString(dir.Item2.Name);
对象o=Command.ExecuteScalar();
int parentId=(int)(十进制)o;
//将每个子目录推送到堆栈上
foreach(dir.Item2.EnumerateDirectories()中的DirectoryInfo子目录)
{
Push(新元组(parentId,subdir));
}
}
返回;
}
这是一次简单的树上漫步。给出这样一张表:
create table dbo.directory
(
id int not null identity(1,1) primary key clustered ,
parent_id int null foreign key references dbo.directory( id ) ,
name varchar(256) collate SQL_Latin1_General_CP1_CI_AS not null , -- case-insensensitive, accent-sensitive
unique ( id , name ) ,
)
go
像这样的课应该对你有用
class DirectoryTreeLoader : IDisposable
{
const string connectionString = "Server=localhost;Database=sandbox;Trusted_Connection=True;" ;
private SqlConnection Connection ;
private SqlCommand Command ;
private bool CommandPrepared ;
private SqlParameter ParentDirectoryId ;
private SqlParameter DirectoryName ;
public DirectoryTreeLoader()
{
Connection = new SqlConnection(connectionString) ;
Command = Connection.CreateCommand() ;
ParentDirectoryId = new SqlParameter( "@parent_id" , SqlDbType.Int , 4 ) ;
DirectoryName = new SqlParameter( "@name" , SqlDbType.VarChar , 256 ) ;
ParentDirectoryId.IsNullable = true ;
DirectoryName.IsNullable = false ;
Command.Parameters.Add( ParentDirectoryId ) ;
Command.Parameters.Add( DirectoryName ) ;
Command.CommandType = CommandType.Text ;
Command.CommandText = @"
insert dbo.directory ( parent_id , name ) values ( @parent_id , @name ) ;
select id = scope_identity() ;
".Trim() ;
return ;
}
public void Load( DirectoryInfo root )
{
if ( Connection.State == ConnectionState.Closed )
{
Connection.Open() ;
Command.Prepare() ;
}
Visit( null , root ) ;
return ;
}
private void Visit( int? parentId , DirectoryInfo dir )
{
// insert the current directory
ParentDirectoryId.SqlValue = parentId.HasValue ? new SqlInt32( parentId.Value ) : SqlInt32.Null ;
DirectoryName.SqlValue = new SqlString( dir.Name ) ;
object o = Command.ExecuteScalar() ;
int id = (int)(decimal) o ;
// visit each subdirectory in turn
foreach ( DirectoryInfo subdir in dir.EnumerateDirectories() )
{
Visit(id,subdir) ;
}
return ;
}
public void Dispose()
{
if ( Command != null )
{
Command.Cancel();
Command.Dispose();
Command = null ;
}
if ( Connection != null )
{
Connection.Dispose() ;
Connection = null ;
}
return ;
}
}
用法
static void Main( string[] args )
{
DirectoryInfo root = new DirectoryInfo( @"c:\inetpub" ) ;
using ( DirectoryTreeLoader loader = new DirectoryTreeLoader() )
{
loader.Load(root) ;
}
return ;
}
如果要消除递归的Visit()
,只需使用堆栈:
public void Load( DirectoryInfo root )
{
if ( Connection.State == ConnectionState.Closed )
{
Connection.Open() ;
Command.Prepare() ;
}
Stack<Tuple<int?,DirectoryInfo>> pending = new Stack<Tuple<int?, DirectoryInfo>>();
pending.Push(new Tuple<int,DirectoryInfo>(null,root) ) ;
while ( pending.Count > 0 )
{
Tuple<int?,DirectoryInfo> dir = pending.Pop() ;
// insert the current directory
ParentDirectoryId.SqlValue = dir.Item1.HasValue ? new SqlInt32( dir.Item1.Value ) : SqlInt32.Null ;
DirectoryName.SqlValue = new SqlString( dir.Item2.Name ) ;
object o = Command.ExecuteScalar() ;
int parentId = (int)(decimal) o ;
// push each subdirectory onto the stack
foreach ( DirectoryInfo subdir in dir.Item2.EnumerateDirectories() )
{
pending.Push( new Tuple<int?, DirectoryInfo>(parentId,subdir));
}
}
return ;
}
公共无效加载(目录信息根目录)
{
if(Connection.State==ConnectionState.Closed)
{
Connection.Open();
Command.Prepare();
}
堆栈挂起=新堆栈();
Push(新元组(null,root));
同时(挂起。计数>0)
{
Tuple dir=pending.Pop();
//插入当前目录
ParentDirectoryId.SqlValue=dir.Item1.HasValue?新的SqlInt32(dir.Item1.Value):SqlInt32.Null;
董事会