我有一个非常复杂的关系数据库,这使我一遍又一遍地使用相同的代码。我正在尝试使用相当复杂的TableRow类来清理它,但是我遇到了一个主要问题。我能解释我想要做的最好的方法是通过一些示例代码:
public abstract class TableRow
{
public abstract string TableName { get; }
public abstract string PrimaryKey { get; }
//there's a lot of these sort of methods for multi-to-multi links, links by two columns, etc
protected T GetLinkedRow<T>() where T : TableRow
{
//here I need to get TableName and PrimaryKey (without creating a new instance of T)
}
}
public class Person : TableRow
{
public override string TableName { get { return "People"; } }
public override string PrimaryKey { get { return "PersonID"; } }
}
public class Dog : TableRow
{
public override string TableName { get { return "Dogs"; } }
public override string PrimaryKey { get { return "DogID"; } }
public Person GetOwner() { return GetLinkedRow<Person>(); }
}
现在我意识到这不是我想要实现的目标,因为我可以创建一个具有TableName或PrimaryKey变量值的类,但我不会这样做。我希望能够覆盖静态属性,但我知道这是不可能的。我以前每个表都有一个类,但这意味着有70个相当无用的类,这就是我想要避免的。解决这类问题的更好方法是什么?
更新
我最终创建了一个新的T实例以获取TableName,因为我将初始化新实例。尽管SLaks的解决方案比这更好,但它并不能保证派生类具有TableName和PrimaryKey属性。对于大多数人来说,SLaks的解决方案会更合适,所以我会将其标记为已接受的答案。
protected T GetLinkedRow<T>() where T : TableRow, new()
{
T row = new T();
DbDataReader reader = ExecuteReader("SELECT * FROM [" + row.TableName + "] WHERE [" + this.PrimaryKey + "] = " + this.ID);
if(!reader.Read())
throw new Exception("No linked row found");
row.Load(reader);
return row;
}
//here's the reason I didn't really want to do this in the first place. Many-to-many relationship. quite messy
protected IEnumerable<T> GetLinkedRows<T>(string junctionTable) where T : TableRow, new()
{
T row = new T();
DbDataReader reader = ExecuteReader("SELECT * FROM [" + row.TableName + "] INNER JOIN [" + junctionTable + "] ON [" + row.TableName + "].[" + row.PrimaryKey + "] = [" + junctionTable + "].[" + row.PrimaryKey + "] WHERE [" + junctionTable + "].[" + this.PrimaryKey + "] = " + this.ID;
while(reader.Read()) {
row.Load(reader);
yield return row;
if(reader.HasRows)
row = new T();
}
}
答案 0 :(得分:1)
在没有实例的情况下调用虚方法(get_TableName
)是完全不可能的。
相反,您可以在类上使用属性,并调用typeof(T).GetCustomAttributes(typeof(YourAttribute), false)
答案 1 :(得分:0)
基于更新的信息...
为什么要这么麻烦?为什么不使用一个抽象方法(或者更好的是,一个接口)来定义方法“GetLinkedRow”,具体实现可以在其中提供细节。
也就是说,你知道Dog的链接行总是Person,所以你有一个接口(警告:未编译!)
public interface ILinkedRow
{
public TableRow GetLinkedRow();
}
然后Dog有了这个实现:
public class Dog : TableRow, ILinkedRow
{
//Implementation here
public TableRow GetLinkedRow()
{
Person p = //implement method
return p
}
}
您的处理代码可以忽略返回的行是Person(如果它永远不需要知道)的事实,或者将其强制转换为(Person)myDog.GetLinkedRow();