[英]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.