OOP 和 C# 中的自引用
Self-Reference in OOP & C#
考虑以下 table :
FkName SchemaName Table Column RefTable RefColumn
FK_Factory_Person dbo Factory PersonId Person Id
FK_Car_Person dbo Car PersonId Person Id
FK_Factory_Car dbo Factory CarId Car Id
我想创建依赖关系class来保存依赖数据
所以我写了一个自引用class任何依赖都可以有依赖
public class Dependency
{
public string TableName { get; set; } // RefTable
public string ColumnName { get; set; } //RefColumn
public List<Dependency> Dependencies { get; set; } // Table
}
但我不知道怎么填 class :
- TableName=Person , ColumnName=Id , Dependencies=Factory,Car
--TableName=Car , ColumnName=Id , Dependencies=Factory
Factory
'
'---- Person
'---- Car
Car
'
'---- Person
任何人都可以帮我提交依赖关系 class 递归 吗?
解决方案:
public class Link
{
public string FKName { get; set; }
public string SchemaName { get; set; }
public string Table { get; set; }
public string Column { get; set; }
public string RefTable { get; set; }
public string RefColumn { get; set; }
}
public class Dependency
{
public string TableName { get; set; } // RefTable
public string ColumnName { get; set; } //RefColumn
public List<Dependency> Dependencies { get; set; } // Table
}
private static void ProcessItem(Dependency target, List<Dependency> dictionary)
{
if(target.Dependencies != null)
foreach(var dep in target.Dependencies)
{
var children = dictionary.Where(x => x.TableName == dep.TableName).FirstOrDefault();
dep.Dependencies = children == null ? null : children.Dependencies;
ProcessItem(dep, dictionary);
}
}
public static List<Dependency> ProcessItems(List<Link> links)
{
var initial = links.GroupBy(x => new { x.RefTable, x.RefColumn })
.Select(x => new Dependency {
TableName = x.Key.RefTable,
ColumnName = x.Key.RefColumn,
Dependencies = x.Select(y => new Dependency {
TableName = y.Table,
ColumnName = y.Column
}).ToList()
}).ToList();
var js = new JavaScriptSerializer();
var temp = js.Deserialize<List<Dependency>>(js.Serialize(initial));
initial.ForEach(x => ProcessItem(x, temp));
return initial;
}
实施:
var links = new List<Link> {
new Link { FKName = "FK_Factory_Person", SchemaName = "dbo", Table = "Factory", Column = "PersonId", RefTable = "Person", RefColumn = "Id" },
new Link { FKName = "FK_Car_Person", SchemaName = "dbo", Table = "Car", Column = "PersonId", RefTable = "Person", RefColumn = "Id" },
new Link { FKName = "FK_Factory_Car", SchemaName = "dbo", Table = "Factory", Column = "CarId", RefTable = "Car", RefColumn = "Id" },
new Link { FKName = "FK_TEST", SchemaName = "dbo", Table = "Person", Column = "TestId", RefTable = "Test", RefColumn = "Id" }
};
var answer = ProcessItems(links);
P.S. If you have circular dependency, StackOveflowException will be
thrown.
考虑以下 table :
FkName SchemaName Table Column RefTable RefColumn
FK_Factory_Person dbo Factory PersonId Person Id
FK_Car_Person dbo Car PersonId Person Id
FK_Factory_Car dbo Factory CarId Car Id
我想创建依赖关系class来保存依赖数据
所以我写了一个自引用class任何依赖都可以有依赖
public class Dependency
{
public string TableName { get; set; } // RefTable
public string ColumnName { get; set; } //RefColumn
public List<Dependency> Dependencies { get; set; } // Table
}
但我不知道怎么填 class :
- TableName=Person , ColumnName=Id , Dependencies=Factory,Car
--TableName=Car , ColumnName=Id , Dependencies=Factory
Factory
'
'---- Person
'---- Car
Car
'
'---- Person
任何人都可以帮我提交依赖关系 class 递归 吗?
解决方案:
public class Link
{
public string FKName { get; set; }
public string SchemaName { get; set; }
public string Table { get; set; }
public string Column { get; set; }
public string RefTable { get; set; }
public string RefColumn { get; set; }
}
public class Dependency
{
public string TableName { get; set; } // RefTable
public string ColumnName { get; set; } //RefColumn
public List<Dependency> Dependencies { get; set; } // Table
}
private static void ProcessItem(Dependency target, List<Dependency> dictionary)
{
if(target.Dependencies != null)
foreach(var dep in target.Dependencies)
{
var children = dictionary.Where(x => x.TableName == dep.TableName).FirstOrDefault();
dep.Dependencies = children == null ? null : children.Dependencies;
ProcessItem(dep, dictionary);
}
}
public static List<Dependency> ProcessItems(List<Link> links)
{
var initial = links.GroupBy(x => new { x.RefTable, x.RefColumn })
.Select(x => new Dependency {
TableName = x.Key.RefTable,
ColumnName = x.Key.RefColumn,
Dependencies = x.Select(y => new Dependency {
TableName = y.Table,
ColumnName = y.Column
}).ToList()
}).ToList();
var js = new JavaScriptSerializer();
var temp = js.Deserialize<List<Dependency>>(js.Serialize(initial));
initial.ForEach(x => ProcessItem(x, temp));
return initial;
}
实施:
var links = new List<Link> {
new Link { FKName = "FK_Factory_Person", SchemaName = "dbo", Table = "Factory", Column = "PersonId", RefTable = "Person", RefColumn = "Id" },
new Link { FKName = "FK_Car_Person", SchemaName = "dbo", Table = "Car", Column = "PersonId", RefTable = "Person", RefColumn = "Id" },
new Link { FKName = "FK_Factory_Car", SchemaName = "dbo", Table = "Factory", Column = "CarId", RefTable = "Car", RefColumn = "Id" },
new Link { FKName = "FK_TEST", SchemaName = "dbo", Table = "Person", Column = "TestId", RefTable = "Test", RefColumn = "Id" }
};
var answer = ProcessItems(links);
P.S. If you have circular dependency, StackOveflowException will be thrown.