好的,我有3个课程:教师,学生和数据库。我想从数据库中读取数据并将其放在教师或学生中。所以我必须写这样的东西:
public Teacher dbSelect(string Table="Teacher")
{
Table = char.ToUpper(Table[0]) + Table.Substring(1);
string query = "SELECT * FROM " + Table + ";";
return dbConnect(query, true);
}
但我必须使用学生返回的确切方法:
public Student dbSelect(string Table="Student")
{
Table = char.ToUpper(Table[0]) + Table.Substring(1);
string query = "SELECT * FROM " + Table + ";";
return dbConnect(query, true);
}
现在我可以在 ViewModel 中编写每个,但我想将它们放在数据库类中。有没有办法做到这一点?
(我知道我可以将它们列在列表中,然后使用该列表,但只是想知道是否有办法!)
更新 我忘了把 dbConnect 放在这里,所以:
public List<Teacher> dbConnect(string query)
{
SQLiteConnection conn = null;
SQLiteCommand command = null;
SQLiteDataReader reader = null;
Teacher result = new Teacher(null, null, null, null, null, null, null, null);
// try
{
conn = new SQLiteConnection(db.db);
conn.Open();
command = new SQLiteCommand(query, conn);
reader = command.ExecuteReader();
}
// catch (Exception ex) { }
while (reader.Read())
{
Teacher temp = new Teacher(
reader[0].ToString(),
reader[1].ToString(),
reader[2].ToString(),
reader[3].ToString(),
reader[4].ToString(),
reader[5].ToString(),
reader[6].ToString(),
reader[7].ToString()
);
result.Items.Add(temp);
}
conn.Close();
return result.Items;
}
学生确实存在但返回:
public List<Student> dbConnect(string query)
{
...
}
答案:我有一个基础课程,当然希望返回一个特定类型的列表,所以我使用 @Jauch 回答,但返回列表。
答案 0 :(得分:0)
这是一个关于如何做你想做的事情的想法,改编自我的代码:
public class BaseClass<T>
where T : new ()
{
protected List<object> list;
protected string query;
protected PropertyInfo[] fProperties;
protected Assembly fStoreAssembly;
public BaseClass()
{
list = new List<T>();
fStoreAssembly = Assembly.GetAssembly (typeof(T));
fProperties = typeof(T).GetProperties();
}
public void Read()
{
SQLiteConnection conn = null;
SQLiteCommand command = null;
SQLiteDataReader reader = null;
try
{
conn = new SQLiteConnection(db.db);
conn.Open();
command = new SQLiteCommand(query, conn);
reader = command.ExecuteReader();
StoreResults (reader);
conn.Close();
}
catch (Exception ex)
{
//deal with the exception here
}
}
//Store results walks through all the records returned and
//creates new instances of the store object and saves in the list,
//using reflection
protected void StoreResults (SQLiteDataReader reader)
{
if (fProperties == null)
throw new Exception ("Store type definition is missing");
while (reader.Read ())
{
object newStoreItem = fStoreAssembly.CreateInstance (typeof(T).FullName);
foreach (PropertyInfo pi in fProperties)
{
string lcName = pi.Name.ToLower ();
if (HasColumn(reader, lcName))
{
if (!reader.IsDBNull(reader.GetOrdinal(lcName)))
pi.SetValue(newStoreItem, reader[lcName], null);
}
}
list.Add (newStoreItem);
}
}
public bool HasColumn (SQLiteDataReader reader, string columnName)
{
foreach (DataRow row in reader.GetSchemaTable().Rows)
{
if (row ["ColumnName"].ToString () == columnName)
return true;
}
return false;
}
}
在这里你将如何创建教师和学生
public class TeacherInfo
{
//Properties for store info from database
}
public class Teacher : BaseClass<TeacherInfo>
{
public Teacher ()
: BaseClass()
{
query = "whatever you want here"
}
}
public class StudentInfo
{
//Properties for store info from database
}
public class Student : BaseClass<StudentInfo>
{
public Student ()
: BaseClass()
{
query = "whatever you want here";
}
}
由于Read例程是公共的,您可以从任何教师或学生实例调用Read。 您甚至可以创建它们并存储为BaseClass并直接使用它,如果您不需要知道它是学生还是教师(对于常见的例程等)
这不是一个广泛的例子,但只是指向可以用来使代码更通用的方向。
答案 1 :(得分:0)
您可以遵循使用接口的语义来返回值,然后将返回类型转换为适当的语句,或者使用基类(接口会更好,因为您仍然可以在实现时将其他类扩展为基类接口)。实体接口可以创建如下,
public interface SchoolEntity {
// Provide the similar properties as members of this interface.
}
然后,您可以在Teacher
和Student
中实施此界面。
public class Student : SchoolEntity { }
public class Teacher : SchoolEntity { }
最后,通过使用枚举可以使参数更加清晰。阅读时它们会更清晰,而不是具有相同的参数类型。 请注意,函数重载不会将返回类型视为签名差异。
enum Entity { Teacher, Student }
然后您可以检查要返回的数据。
public SchoolEntity dbSelect(Entity type)
{
switch(type) {
case Teacher:
var query = "SELECT * FROM Teacher";
return dbConnect(query, true);
// Rest of the cases.
}
}
请注意,您的SQL语句对SQL注入是开放的,任何人都可以删除表,或执行可以传递给引擎的操作。
使用列表不是一个好主意。毕竟,你会回到什么名单?那会是public List<Teacher> dbSelect
还是public List<Student> dbSelect
?对此的答案和解决方案是使用相同类型备份这两种类型。
dbSelect
功能请注意,您仍然只返回Teacher
类型,那么为什么您要学生?你一定要把它丢回来。事实上,如果我不得不发展这个。我必须使用dbSelect
函数将Entity
作为参数,以便将所有数据库请求和处理保存在单个函数中。
public List<Teacher> dbConnect(Entity type)
{
SQLiteConnection conn = null;
SQLiteCommand command = null;
SQLiteDataReader reader = null;
Teacher result = null; // Can be set to null.
// try
{
conn = new SQLiteConnection(db.db);
conn.Open();
string query;
// This way, leave the function to build the query.
if(type == Entity.Teacher) {
query = "SELECT * FROM Teacher";
} else {
query = "SELECT * FROM Student";
}
command = new SQLiteCommand(query, conn);
reader = command.ExecuteReader();
}
// catch (Exception ex) { }
while (reader.Read())
{
if(type == Entity.Teacher) {
Teacher temp = new Teacher(
reader[0].ToString(),
reader[1].ToString(),
reader[2].ToString(),
reader[3].ToString(),
reader[4].ToString(),
reader[5].ToString(),
reader[6].ToString(),
reader[7].ToString()
);
result.Items.Add(temp);
} else {
// Add the student.
}
}
conn.Close();
return result;
}
现在,在此代码中,您知道result
的类型为Teacher
。那里没有列表,这使你的代码有点混乱。听从我的建议:重新编写代码。
还请浏览以下有用链接:
Explicit Interface Implementation
https://en.wikipedia.org/wiki/SQL_injection
Signatures and overloading