[英]Loading related objects in memory (without an ORM)
我正在使用ADO.NET將一堆數據從數據庫讀取到內存中的對象中。
這是我的域模型:
// Question.cs
public class Question
{
public int ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public IEnumerable<Tag> Tags { get; set; }
}
// Tag.cs
public class Tag
{
public int ID { get; set; }
public string Name { get; set; }
}
在檢索問題列表時,我想獲取每個問題的相關標簽。 我可以做到這一點,如下所示:
// QuestionRepository.cs
public IList<Question> FindAll()
{
var questions = new List<Question>();
using (SqlConnection conn = DB.GetSqlConnection())
{
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = "select * from questions";
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
Question question = new Question();
// Populate the question object using reader
question.Load(reader);
questions.Add(question);
}
reader.Close();
}
}
return questions;
}
// Question.cs
public void Load(SqlDataReader reader)
{
ID = int.Parse(reader["ID"].ToString());
Title = reader["Title"].ToString();
Description = reader["Description"].ToString();
// Use Tag Repository to find all the tags for a particular question
Tags = tagRepository.GetAllTagsForQuestionById(ID);
}
return questions;
}
// TagRepository.cs
public List<Tag> GetAllTagsForQuestionById(int id)
{
List<Tag> tags = new List<Tag> ();
// Build sql query to retrive the tags
// Build the in-memory list of tags
return tags;
}
我的問題是,是否有用於從數據庫中獲取相關對象的最佳實踐/模式?
我在加載相關數據時遇到的大多數SO問題都為實體框架提供了解決方案。 這個重復的問題沒有答案。
即使我的代碼有效,我也想知道其他方法來做到這一點。 針對我的特定問題,我遇到的最接近的解釋是Martin Fowler的Lazy Load模式,我相信它將導致以下實現:
public class Question
{
private TagRepository tagRepo = new TagRepository();
private IList<Tag> tags;
public int ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public IEnumerable<Tag> Tags {
get
{
if (tags == null)
{
tags = tagRepo.GetAllTagsForQuestionById(ID);
}
return tags;
}
}
}
還有其他選擇嗎?
如果您堅持要在ADO.Net中執行此操作,那么我建議對匿名類型LINQ和Enumerable.Range(0,0)使用一些技巧。
首先,您需要創建一個匿名類型的列表(或僅創建一個映射回您的SQL語句的實際類)
var data = Enumerable.Range(0, 0).Select(x => new
{
QestionId = 0,
Title = "Question.Title",
Description = "Question.Description",
TagId = 0,
Name = "Tag.Name"
}).ToList();
接下來是在其中執行ADO.Net的工作,查詢數據庫並獲取結果。
這里的關鍵是編寫一個查詢,該查詢返回一個查詢中要查找的所有數據。
using (var conn = GetConnection())
{
using (var cmd = conn.CreateCommand())
{
//Construct a valid SQL statement that joins questions to tags
cmd.CommandText = "SELECT q.*, t.* FROM questions q JOIN tags t ON 1 = 1";
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
data.Add(new
{
QestionId = reader.IsDBNull(0) ? 0 : int.TryParse(reader.GetValue(0).ToString(), out var qId) ? qId : 0,
Title = reader.IsDBNull(1) ? string.Empty : reader.GetValue(1).ToString(),
Description = reader.IsDBNull(2) ? string.Empty : reader.GetValue(2).ToString(),
TagId = reader.IsDBNull(3) ? 0 : int.TryParse(reader.GetValue(3).ToString(), out var tId) ? tId : 0,
Name = reader.IsDBNull(4) ? string.Empty : reader.GetValue(4).ToString()
});
}
}
}
}
現在您已經用所有行完全填充了列表,只需要將它們轉換回要查找的對象即可。
var questions = data.GroupBy(x => new {x.QestionId, x.Title, x.Description}).Select(y => new Question
{
Id = y.Key.QestionId,
Title = y.Key.Title,
Description = y.Key.Description,
Tags = y.Select(z => new Tag
{
Id = z.TagId,
Name = z.Name
})
}).ToList();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.