gpt4 book ai didi

c# - 如何从 C# 类生成数据库表?

转载 作者:IT王子 更新时间:2023-10-29 03:48:19 25 4
gpt4 key购买 nike

有谁知道为给定类自动生成数据库表的方法吗?我不是在寻找一个完整的持久层——我已经有一个正在使用的数据访问解决方案,但我突然不得不存储来自大量类的大量信息,我真的不想创建所有这些表都是手工制作的。例如,给定以下类:

class Foo
{
private string property1;
public string Property1
{
get { return property1; }
set { property1 = value; }
}

private int property2;
public int Property2
{
get { return property2; }
set { property2 = value; }
}
}

我期望以下 SQL:

CREATE TABLE Foo
(
Property1 VARCHAR(500),
Property2 INT
)

我还想知道您如何处理复杂类型。例如,在前面引用的类中,如果我们将其更改为:

class Foo
{
private string property1;
public string Property1
{
get { return property1; }
set { property1 = value; }
}

private System.Management.ManagementObject property2;
public System.Management.ManagementObject Property2
{
get { return property2; }
set { property2 = value; }
}
}

我该如何处理?

我已经研究过尝试使用反射自己自动生成数据库脚本来枚举每个类的属性,但它很笨拙,而且复杂的数据类型让我感到难过。

最佳答案

真的很晚了,我只花了大约 10 分钟,所以它非常草率,但它确实有效并且会给你一个很好的起点:

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace TableGenerator
{
class Program
{
static void Main(string[] args)
{
List<TableClass> tables = new List<TableClass>();

// Pass assembly name via argument
Assembly a = Assembly.LoadFile(args[0]);

Type[] types = a.GetTypes();

// Get Types in the assembly.
foreach (Type t in types)
{
TableClass tc = new TableClass(t);
tables.Add(tc);
}

// Create SQL for each table
foreach (TableClass table in tables)
{
Console.WriteLine(table.CreateTableScript());
Console.WriteLine();
}

// Total Hacked way to find FK relationships! Too lazy to fix right now
foreach (TableClass table in tables)
{
foreach (KeyValuePair<String, Type> field in table.Fields)
{
foreach (TableClass t2 in tables)
{
if (field.Value.Name == t2.ClassName)
{
// We have a FK Relationship!
Console.WriteLine("GO");
Console.WriteLine("ALTER TABLE " + table.ClassName + " WITH NOCHECK");
Console.WriteLine("ADD CONSTRAINT FK_" + field.Key + " FOREIGN KEY (" + field.Key + ") REFERENCES " + t2.ClassName + "(ID)");
Console.WriteLine("GO");

}
}
}
}
}
}

public class TableClass
{
private List<KeyValuePair<String, Type>> _fieldInfo = new List<KeyValuePair<String, Type>>();
private string _className = String.Empty;

private Dictionary<Type, String> dataMapper
{
get
{
// Add the rest of your CLR Types to SQL Types mapping here
Dictionary<Type, String> dataMapper = new Dictionary<Type, string>();
dataMapper.Add(typeof(int), "BIGINT");
dataMapper.Add(typeof(string), "NVARCHAR(500)");
dataMapper.Add(typeof(bool), "BIT");
dataMapper.Add(typeof(DateTime), "DATETIME");
dataMapper.Add(typeof(float), "FLOAT");
dataMapper.Add(typeof(decimal), "DECIMAL(18,0)");
dataMapper.Add(typeof(Guid), "UNIQUEIDENTIFIER");

return dataMapper;
}
}

public List<KeyValuePair<String, Type>> Fields
{
get { return this._fieldInfo; }
set { this._fieldInfo = value; }
}

public string ClassName
{
get { return this._className; }
set { this._className = value; }
}

public TableClass(Type t)
{
this._className = t.Name;

foreach (PropertyInfo p in t.GetProperties())
{
KeyValuePair<String, Type> field = new KeyValuePair<String, Type>(p.Name, p.PropertyType);

this.Fields.Add(field);
}
}

public string CreateTableScript()
{
System.Text.StringBuilder script = new StringBuilder();

script.AppendLine("CREATE TABLE " + this.ClassName);
script.AppendLine("(");
script.AppendLine("\t ID BIGINT,");
for (int i = 0; i < this.Fields.Count; i++)
{
KeyValuePair<String, Type> field = this.Fields[i];

if (dataMapper.ContainsKey(field.Value))
{
script.Append("\t " + field.Key + " " + dataMapper[field.Value]);
}
else
{
// Complex Type?
script.Append("\t " + field.Key + " BIGINT");
}

if (i != this.Fields.Count - 1)
{
script.Append(",");
}

script.Append(Environment.NewLine);
}

script.AppendLine(")");

return script.ToString();
}
}
}

我将这些类放在一个程序集中进行测试:

public class FakeDataClass
{
public int AnInt
{
get;
set;
}

public string AString
{
get;
set;
}

public float AFloat
{
get;
set;
}

public FKClass AFKReference
{
get;
set;
}
}

public class FKClass
{
public int AFKInt
{
get;
set;
}
}

它生成了以下 SQL:

CREATE TABLE FakeDataClass
(
ID BIGINT,
AnInt BIGINT,
AString NVARCHAR(255),
AFloat FLOAT,
AFKReference BIGINT
)


CREATE TABLE FKClass
(
ID BIGINT,
AFKInt BIGINT
)


GO
ALTER TABLE FakeDataClass WITH NOCHECK
ADD CONSTRAINT FK_AFKReference FOREIGN KEY (AFKReference) REFERENCES FKClass(ID)
GO

一些进一步的想法...我会考虑向您的类添加一个属性,例如 [SqlTable],这样它只会为您想要的类生成表。此外,这可以清理一吨,修复错误,优化(FK Checker 是个笑话)等等......只是为了让你开始。

关于c# - 如何从 C# 类生成数据库表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47239/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com