簡體   English   中英

C#通用綁定

[英]C# Generic binding

我正在為學校分配作業,並嘗試為學習而實現盡可能多的功能。 因此,我做了一個通用的映射器,將數據庫表映射到對象,以查看可能的情況。 在這種情況下,Db是本地的。 我知道我要處理大量的呼叫,應該以不同的方式解決這個問題,但是...

一切都按預期工作,但當一個類具有另一個類的Collection時除外。

例:

class Student {

public int Id { get; set; }
public string Name { get; set; }
}

我的方法用於填充數據庫中所有學生的列表。

public List<TModel> MapEntitiesFromDb<TModel>(string tablename, string customquery = "") where TModel : class, new() 
    {
        try
        {
            sql = ValidateSelectSql(tablename, customquery);
        }
        catch (AccessViolationException ex) { Console.WriteLine(ex.Message); }

        command.CommandText = sql;
        command.Connection = conn;

        List<TModel> list = new List<TModel>();
        try
        {
            using (conn)
            {
                Type t = new TModel().GetType();

                conn.Open();
                using (reader = command.ExecuteReader())
                {

                    if (t.GetProperties().Length != reader.FieldCount)
                        throw new Exception("There is a mismatch between the amount of properties and the database columns. Please check the input code and try again.");

                    //Possible check is to store each column and property name in arrays and match them to a new boolean array, if there's 1 false throw an exception.
                    string columnname;
                    string propertyname;

                    //Pairing properties with columns 
                    while (reader.Read())
                    {
                        TModel obj = new TModel();

                        for (int i = 0; i < reader.FieldCount; i++)
                        {
                            columnname = reader.GetName(i).ToString().ToLower();

                            PropertyInfo[] properties = t.GetProperties();
                            foreach (PropertyInfo propertyinfo in properties)
                            {
                                propertyname = propertyinfo.Name.ToLower();

                                if (propertyname == columnname)
                                {
                                    propertyinfo.SetValue(obj, reader.GetValue(i));
                                    break;
                                }
                            }
                        }

                        list.Add(obj);

                    }
                }
            }
        }
        catch (Exception ex) { Console.WriteLine(ex.Message); }

        return list;
    }

我的ValidateSelectSql只是返回查詢中需要使用的sql字符串。

致電后:

List<Student> = MapEntitiesFromDb<Student>("students");

它將返回一個列表,其中包含所有想要的學生。

例如,當我添加一個集合時,事情就出錯了:

class Student {

public Student()
{
    this.Courses = new List<Course>();

    string customsqlquery = ::: this works and is tested! :::
    Courses = MapEntitiesFromDb<Course>("", customsqlquery);
}

public int Id { get; set; }
public string Name { get; set; }

public ICollection<Course> Courses;
}

課程列表返回為空,並且在我創建對象時發現的調試器工具的幫助下,Id屬性當然為0。 在我的查詢中,我正在過濾學生ID,但是在執行將方法填充到構造函數中的“課程”列表時,該學生的ID始終為0,因為它是在稍后階段設置的,結果將是該列表中沒有課程。

我想知道是否應該在設置其他屬性后檢查ICollection屬性,是否在對象上執行一個方法,然后返回執行構造函數內部的方法?

我不能在TModel上調用任何方法,否則就像找到TModel是否具有collection屬性並調用obj.FillCollection()一樣簡單。 在GetEntitiesFromDb方法中分配Id屬性之后。

我也在考慮遞歸。 再次,我必須查找obj是否具有collection屬性,然后調用GetEntitiesFromDB,但這似乎是不可撤消的,因為我還需要找出<>之間的類型,並且我無法從外部發送任何customquery ...

也許是從另一個角度解決呢?

我真的可以就如何解決這個問題使用一些建議。

解決此問題的最直接方法是讓collection屬性延遲加載所需的內容。 我還建議您使用IEnumerable<T>而不是ICollection<T>因為這表示數據庫中當前內容的只讀視圖,沒有人可以任何方式對其進行修改。

public class Student
{    
    private readonly Lazy<IEnumerable<Course>> courses;

    public int Id { get; set; }
    public IEnumerable<Course> Courses => this.courses.Value;

    public Student()
    {
        this.courses = new Lazy<IEnumerable<Course>>(LoadCourses);
    }

    private IEnumerable<Course> LoadCourses()
    {
        var sql = "custom SQL query that uses this.Id after it's loaded";
        return MapEntitiesFromDb(sql);
    }
}

我只推薦這種方法,因為您提到這只是一個學術練習,可以幫助您了解可用的工具。 在實際的生產環境中,這種方法很快就會變得笨拙,我建議改用Entity Framework(這可能是您可能想了解的其他東西)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM