我正试图摆脱实体框架,因为除了我们的解决方案中的SQL服务器数据库之外,我必须支持HANA数据库。
我正在与小巧玲珑进行一些研究,所以我创建了一个虚拟场景的快速测试环境。
我有以下POCO类似于我的数据库架构(我有更多,但我仅限于显示这些以简化):
enable_if_t
我在存储库中使用以下命令返回所有采用者的列表:
public class Adopter
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public State State { get; set; }
public int StateId { get; set; }
public string Zip { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Fax { get; set; }
public IEnumerable<Pet> Pets { get; set; }
}
public class State
{
public int Id { get; set; }
public string Name { get; set; }
public string Abreviation { get; set; }
}
public class Pet
{
public int Id { get; set; }
public string IdTag { get; set; }
public string Name { get; set; }
public DateTime AdmitionDate { get; set; }
public Status Status { get; set; }
public int StatusId { get; set; }
public string Notes { get; set; }
public DateTime AdoptionDate { get; set; }
public bool IsAdopted { get; set; }
public int? AdopterId { get; set; }
public int Age { get; set; }
public decimal Weight { get; set; }
public string Color { get; set; }
public Breed Breed { get; set; }
public int BreedId { get; set; }
public Gender Gender { get; set; }
public int GenderId { get; set; }
public IEnumerable<PetImage> PetImages { get; set; }
}
public class Status
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
public class Gender
{
public int Id { get; set; }
public string Name { get; set; }
}
如您所见,我正在根据前一个POCO单独检索每个POCO的数据,并在代码中手动执行联接。
这是正确的方法吗?或者我应该使用多个连接进行大查询并通过dapper和LINQ以某种方式映射结果?
答案 0 :(得分:4)
对您的实际解决方案的一种可能的改进是通过使用QueryMultiple扩展,如下所示:
using (SqlConnection connection = new SqlConnection(_connectionString))
{
string query = @"SELECT * FROM Adopters;
SELECT * FROM States;
SELECT * FROM Pets;
SELECT * FROM Status;
SELECT * FROM Genders;";
using (var multi = connection.QueryMultiple(query, null))
{
var adopters = multi.Read<Adopter>();
var states = multi.Read<State>();
var pets = multi.Read<Pet>();
var statuses = multi.Read<Status>();
var genders = multi.Read<Gender>();
foreach (Adopter adp in adopters)
{
adp.State = states.FirstOrDefault(x => x.Id == adp.StateID);
adp.Pets = pets.Where(x => x.IsAdopted &&
x.AdopterID.HasValue &&
x.AdopterID.Value == adp.AdopterID)
.ToList();
foreach(Pet pet in adp.Pets)
{
pet.Status = statuses.FirstOrDefault(x => x.Id == pet.StatusID);
pet.Gender = genders.FirstOrDefault(x => x.Id == pet.GenderID);
}
}
}
}
这样做的好处是,您只需一次访问数据库,然后处理内存中的所有内容。
然而,如果您要检索一个非常大的数据(并且从远程位置),这可能会造成性能损失和内存瓶颈。最好密切关注这种方法,并尽可能尝试某种异步处理和/或分页。
答案 1 :(得分:2)
我不喜欢消极,但是......不要这样做!不要这么想。您想要转储EF,但是您想通过模拟EF来进入陷阱。您的应用程序和数据库之间的桥梁不是一直可以构建的,无论出于何种目的。具体来说,你不应该带回整个表,当然也不要在每一行循环并发出更多查询。您可能会受到不公正的批评,您只是在测试工具!如果是这样,或许告诉我们您正在研究的工具的哪个方面,我们将关注这一点。
Dapper或QueryFirst大大简化了运行查询并消耗了结果,因此只需在您需要时就可以恢复所需内容。然后对于手头的具体工作进行反规范化。为什么查询中没有加入? RDBMS非常棒,而且非常擅长加入。如果您正在加入数据库之外的数据,那么疯狂是唯一的一个词,即使Linq为您提供了超级(类似sql)的语法。 1表对应1类的不假思索假设是许多问题的开始。