簡體   English   中英

C#使用外鍵填充嵌套類

[英]C# Populate nested class using foreign key

我需要將來自兩個單獨的數據庫調用的信息拉回到一個對象中。

考慮以下課程

public class Status
{
    public int StatusId { get; set; }
    public string Name { get; set; }
}
public class Person
{
    public int PersonId { get; set; }
    public Status PersonStatus { get; set; }
}

這些代表兩個數據庫表Persons和Status,它們與Persons表中的StatusId相關。

CREATE TABLE [dbo].[Status](
    [StatusId] [INT] NOT NULL PRIMARY KEY,
    [Name] [NVARCHAR](50) NOT NULL )

CREATE TABLE [dbo].[Persons](
    [PersonId] [int] NOT NULL PRIMARY KEY,
    [StatusId] [int] NOT NULL REFERENCES dbo.Status (StatusId) )

這是獲取人員的過程:

CREATE PROCEDURE dbo.spGetPersons
AS
BEGIN
    SELECT  PersonId ,
            StatusId
    FROM    dbo.Persons
END

然后,我從SqlDataReader讀取數據,構造一個Person對象,並返回一個IList<Person> 為了填充PersonStatus屬性,當前我將StatusId傳遞到輔助過程中,該過程將再次往返數據庫。

IList<Person> People = new List<Person>();
while (reader.Read())
{
    People.Add(new Person()
    {
        PersonId = (int)reader["PersonId"],
        //This causes the extra round trip to the database
        StatusId = new StatusDao().GetStatus((int)reader["StatusId"])
    });
}

StatusDao().GetStatus()僅執行以下過程並構造一個Status對象。

CREATE PROCEDURE dbo.spGetStatus
    @StatusId INT = NULL
AS
    BEGIN
        SELECT  StatusId ,
                Name
        FROM    dbo.Status
        WHERE   @StatusId IS NULL
                OR @StatusId = StatusId
    END

填充PersonStatus屬性的正確方法是什么? 顯然,我不應該為每個Person進行一次額外的數據庫往返之旅。 假設我無法編輯過程,而僅將Name添加到SQL查詢中。

我沒有看到這個問題,用枚舉建議。 在某些情況下,這是一個不錯的選擇,但是我們假設狀態數據會定期更改。 這使得它不再是一種選擇。

我當前未使用ORM。

我無法添加新的存儲過程,也無法編輯現有的存儲過程。 我也不允許使用內聯SQL。

由於您有一個非常奇怪的要求,即無法添加新的存儲過程或使用內聯SQL; 無論如何,它將需要兩次訪問數據庫(除非再次聲明,狀態是可以在枚舉中捕獲的東西)。

如果您有一個Status對象和一個Person對象,並且想要將它們放在一起,則可以使用以下方法:

public static List<Person> GetStatusForPerson(List<Person> people, List<Status> statuses)
{
    List<Person> peopleWithStatuses = new List<Person>();
    foreach (var p in people) 
    {
        Person person = new Person();
        person.PersonId = p.PersonId;
        person.Status = statuses.Where(s => s.StatusId == person.StatusId).FirstOrDefault());

        peopleWithStatuses.Add(person);
    }
    return peopleWithStatuses;
}

要在一次數據庫往返中獲取此信息(對於那些沒有奇怪要求的人):

var persons = new List<Person>();
using (SqlConnection connection = new SqlConnection(connectionString)) {
    string sqlText = "Select p.PersonId, ps.Name, ps.StatusId FROM Person p INNER JOIN PersonStatus ps on p.StatusID = ps.StatusId WHERE p.PersonId = @personId";
    SqlCommand command = new SqlCommand();
    command.Parameters.Add("@personId", SqlDbType.Int);
    command.Parameters["@personId"].Value = personId;
    connection.Open();
    using (SqlDataReader reader = command.ExecuteReader()) {
        while (reader.Read()) 
        {
            var person = new Person();
            var status = new PersonStatus();
            person.PersonID = reader["PersonId"]; 
            status.StatusId = reader["StatusId"];
            status.Name = reader["Name"];
            person.Status = status;
            persons.Add(person);
        }
    }
}
return persons;

使用枚舉

如果Status是一系列整數常量(很像enum ),那么您可以簡單地使用enum並存儲可能的狀態。

如果Status動態地添加或刪除值,那么在不使用ORM時,您必須求助於恢復數據的常規方法: A DataReader

暫無
暫無

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

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