我需要将两个单独的数据库调用中的信息撤回到一个对象中。
考虑以下课程
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查询中。
我确实看到了使用枚举器提出的this问题。在某些情况下,这是一个不错的选择,但我们只是假设状态数据会定期更改。这使得这不再是一种选择。
我目前没有使用ORM。
我无法添加新的存储过程,也无法编辑现有的存储过程。我也不允许使用内联SQL。
答案 0 :(得分:3)
由于您有一个相当奇怪的要求,即无法添加新的存储过程或使用内联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
。