.NET C# 在应用程序内传输数据的最佳对象
.NET C# best object to transport data within application
出于可读性和更好的可测试性的原因,我喜欢将我的应用程序代码组织成层 - 所以我有多个项目,每个项目都有多个文件夹结构,每个文件夹可能有多个 classes,带有命名空间符合拓扑。这里没什么特别的 - 大多数开发人员以类似的方式构建代码。
在我的纯数据层中,我需要执行 T-SQL Stored Procedure
来检索只读数据集 - 我只需要遍历行并读取列值。
在另一层中,我需要对行集执行各种数据转换(示例:编写要提供给另一个应用程序的配置文件)。
通常在我的数据层 class 我会使用 SqlDataReader
迭代行,提取列值,并执行内联数据转换。
但我更愿意将此功能分解为单独的 class。
所以我需要一个断开连接的数据传输容器。可能性是 DataSet
、DataTable
、DataView
、DataRowCollection
- 但也许这些对我的目的来说有点矫枉过正。
有哪些最佳class传输只读数据的建议?
您可以采用几种不同的策略来执行此操作:
- 使用 LINQ to sql 避免重复行列表(第一次填充数据表或 pocos 列表,第二次进行转换)
- 定义一个 IDataTransformer 接口并将其传递给您的数据访问加载方法,并让该方法在从 SqlDataReader 加载数据时使用转换器来调整数据。
- 将 Entity Framework 用于自定义查询。
选项 1 和选项 3 有很多资源,所以我将在这里处理选项 2。
假设您使用以下方法定义了一个 ISomethingDataAccess
接口:
public interface ISomethingDataAccess
{
List<T> LoadAll<T>(Func<IDataReader, T> transformer);
}
transformer
参数将接受包含回调的参数,该回调将接受 IDataReader
和 return 类型 T
的实例。
LoadAll<T>
方法是一种通用方法,它允许调用者确定将从 IDataReader
创建的对象的类型,然后填充到 List<T>
return从方法中编辑。
在你的实现中,你会做这样的事情:
public class SqlSomethingDataAccess : ISomethingDataAccess
{
public List<T> LoadAll<T>(Func<IDataReader, T> transformer)
{
// ... Setup connection and command, etc ...
var returnList = new List<T>();
var reader = command.ExecuteReader(); // <- from setup steps above
while(!reader.MoveNext())
{
returnList.Add(transformer(reader));
}
return returnList;
}
}
根据您的需要自定义方法。现在您已经将转换问题分离到数据访问之外 class.
像这样使用它:
public class SomethingBusiness()
{
public List<SomeTransformedThing> LoadAllSomethingsAsTransformedSomethings()
{
var returnList = this.dataAccess.LoadAll<SomeTransformedThing>
(reader=>new SomeTransformedThing()
{
// ... transform data from reader here
});
return returnList;
}
}
出于可读性和更好的可测试性的原因,我喜欢将我的应用程序代码组织成层 - 所以我有多个项目,每个项目都有多个文件夹结构,每个文件夹可能有多个 classes,带有命名空间符合拓扑。这里没什么特别的 - 大多数开发人员以类似的方式构建代码。
在我的纯数据层中,我需要执行 T-SQL Stored Procedure
来检索只读数据集 - 我只需要遍历行并读取列值。
在另一层中,我需要对行集执行各种数据转换(示例:编写要提供给另一个应用程序的配置文件)。
通常在我的数据层 class 我会使用 SqlDataReader
迭代行,提取列值,并执行内联数据转换。
但我更愿意将此功能分解为单独的 class。
所以我需要一个断开连接的数据传输容器。可能性是 DataSet
、DataTable
、DataView
、DataRowCollection
- 但也许这些对我的目的来说有点矫枉过正。
有哪些最佳class传输只读数据的建议?
您可以采用几种不同的策略来执行此操作:
- 使用 LINQ to sql 避免重复行列表(第一次填充数据表或 pocos 列表,第二次进行转换)
- 定义一个 IDataTransformer 接口并将其传递给您的数据访问加载方法,并让该方法在从 SqlDataReader 加载数据时使用转换器来调整数据。
- 将 Entity Framework 用于自定义查询。
选项 1 和选项 3 有很多资源,所以我将在这里处理选项 2。
假设您使用以下方法定义了一个 ISomethingDataAccess
接口:
public interface ISomethingDataAccess
{
List<T> LoadAll<T>(Func<IDataReader, T> transformer);
}
transformer
参数将接受包含回调的参数,该回调将接受 IDataReader
和 return 类型 T
的实例。
LoadAll<T>
方法是一种通用方法,它允许调用者确定将从 IDataReader
创建的对象的类型,然后填充到 List<T>
return从方法中编辑。
在你的实现中,你会做这样的事情:
public class SqlSomethingDataAccess : ISomethingDataAccess
{
public List<T> LoadAll<T>(Func<IDataReader, T> transformer)
{
// ... Setup connection and command, etc ...
var returnList = new List<T>();
var reader = command.ExecuteReader(); // <- from setup steps above
while(!reader.MoveNext())
{
returnList.Add(transformer(reader));
}
return returnList;
}
}
根据您的需要自定义方法。现在您已经将转换问题分离到数据访问之外 class.
像这样使用它:
public class SomethingBusiness()
{
public List<SomeTransformedThing> LoadAllSomethingsAsTransformedSomethings()
{
var returnList = this.dataAccess.LoadAll<SomeTransformedThing>
(reader=>new SomeTransformedThing()
{
// ... transform data from reader here
});
return returnList;
}
}