【发布时间】:2021-01-28 22:28:28
【问题描述】:
当我执行下面的代码时,它会生成一个异常。我哪里错了?
产生异常的代码extractor.Extract:
public Visit Get(long id, bool loadGraph = false) {
const string sqlVisit = @"SELECT * FROM Visit WHERE Id = @VisitId;";
const string sqlCC = @"SELECT * FROM ChiefComplaint WHERE VisitId = @VisitId;";
var sqlParam = new { VisitId = id };
if (loadGraph) {
using (var extractor = base.ExecuteQueryMultiple(sqlVisit + sqlCC, sqlParam)) {
/*fails with exception*/var v = extractor.Extract<Visit>().FirstOrDefault();
var cc = extractor.Extract<ChiefComplaint>().AsList();
return new Visit(v.Id, v.DateOfService, cc);
}
}
else {
using (var extractor = base.ExecuteQueryMultiple(sqlVisit, sqlParam)) {
return extractor.Extract<Visit>().FirstOrDefault();
}
}
}
访问表对应的域实体:
public class Visit : BaseEntity {
private List<ChiefComplaint> _chiefComplaints = new List<ChiefComplaint>();
public IReadOnlyList<ChiefComplaint> ChiefComplaints => _chiefComplaints.ToList();
public DateTime DateOfService { get; }
public Visit(long id, DateTime dateOfService, IEnumerable<ChiefComplaint> chiefComplaints) : base(id) {
this.DateOfService = dateOfService;
_chiefComplaints.AddRange(chiefComplaints);
}
}
所有域实体都继承自的基础域实体:
public abstract class BaseEntity {
public long Id { get; }
protected BaseEntity(long id) {
this.Id = id;
}
public override bool Equals(object obj) {
if (!(obj is BaseEntity other))
return false;
if (ReferenceEquals(this, other))
return true;
if (this.GetType() != other.GetType())
return false;
if (this.Id == 0 || other.Id == 0)
return false;
return this.Id == other.Id;
}
public static bool operator ==(BaseEntity a, BaseEntity b) {
if (a is null && b is null)
return true;
if (a is null || b is null)
return false;
return a.Equals(b);
}
public static bool operator !=(BaseEntity a, BaseEntity b) {
return !(a == b);
}
public override int GetHashCode() {
return (this.GetType().ToString() + this.Id).GetHashCode();
}
}
访问和首席投诉表:
CREATE TABLE [dbo].[Visit] (
[Id] BIGINT IDENTITY (1, 1) NOT NULL,
[DateOfService] DATETIME2 (7) NOT NULL
);
CREATE TABLE [dbo].[ChiefComplaint] (
[Id] BIGINT IDENTITY (1, 1) NOT NULL,
[Description] NVARCHAR (MAX) NULL,
[HpiId] BIGINT NULL,
[VisitId] BIGINT NULL
);
例外:
System.NullReferenceException
HResult=0x80004003
Message=Object reference not set to an instance of an object.
Source=RepoDb
StackTrace:
at RepoDb.Reflection.Compiler.<>c__DisplayClass62_0`1.<GetClassPropertyParameterInfos>b__1(ParameterInfo parameterInfo)
at System.Collections.Generic.List`1.ForEach(Action`1 action)
at RepoDb.Reflection.Compiler.GetClassPropertyParameterInfos[TResult](IEnumerable`1 readerFieldsName, IDbSetting dbSetting)
at RepoDb.Reflection.Compiler.GetMemberBindingsForDataEntity[TResult](ParameterExpression readerParameterExpression, IEnumerable`1 readerFields, IDbSetting dbSetting)
at RepoDb.Reflection.Compiler.CompileDataReaderToDataEntity[TResult](DbDataReader reader, IEnumerable`1 dbFields, IDbSetting dbSetting)
at RepoDb.Reflection.Compiler.CompileDataReaderToType[TResult](DbDataReader reader, IEnumerable`1 dbFields, IDbSetting dbSetting)
at RepoDb.Reflection.FunctionFactory.CompileDataReaderToType[TResult](DbDataReader reader, IEnumerable`1 dbFields, IDbSetting dbSetting)
at RepoDb.FunctionCache.DataReaderToTypeCache`1.Get(DbDataReader reader, IEnumerable`1 dbFields, IDbSetting dbSetting)
at RepoDb.FunctionCache.GetDataReaderToTypeCompiledFunction[TResult](DbDataReader reader, IEnumerable`1 dbFields, IDbSetting dbSetting)
at RepoDb.Reflection.DataReader.<ToEnumerable>d__0`1.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at RepoDb.Extensions.EnumerableExtension.AsList[T](IEnumerable`1 value)
at RepoDb.QueryMultipleExtractor.Extract[TEntity](Boolean isMoveToNextResult)
at Repositories.VisitRepository.Get(Int64 id, Boolean loadGraph)
我尝试按照 RepoDb 上的文档实现属性处理程序,但没有成功。下面是我如何实现属性处理程序。
public class ChiefComplaintPropertyHandler : IPropertyHandler<string, ChiefComplaint> {
public ChiefComplaint Get(string input, ClassProperty property) {
return JsonConvert.DeserializeObject<ChiefComplaint>(input);
}
public string Set(ChiefComplaint input, ClassProperty property) {
return JsonConvert.SerializeObject(input);
}
}
在我的数据层项目中,我有一个 DependencyInjection.cs 类,它实现了配置要求并在 ConfigureServices 中被调用,如下所示。这是我指定 FluentMapper 映射的地方。
public static class DependencyInjection {
public static IServiceCollection AddDataCoreServices(this IServiceCollection services, IConfigurationSection dbConfigSection) {
SqlServerBootstrap.Initialize();
FluentMapper
.Entity<Visit>()
.PropertyHandler<ChiefComplaintPropertyHandler>(v => v.ChiefComplaints, true);
services.Configure<AppSetting>(dbConfigSection);
services.AddTransient<IUnitOfWork, UnitOfWork>();
services.AddTransient<IVisitRepository, VisitRepository>();
return services;
}
}
Web api 项目中 Startup.cs 的 ConfigureServices 部分。
public void ConfigureServices(IServiceCollection services) {
services.AddControllers();
services.AddDataCoreServices(Configuration.GetSection("AppSettings"));
}
【问题讨论】:
-
我将把它作为一个问题提交到我们的 Github 页面上。可以分享一下模型和表结构吗?
-
我已更新原始帖子以反映您的要求。感谢您的帮助!
-
谢谢,我们会尽快回复您。
-
我相信 Extract
() 调用不喜欢传递给 Visit 构造函数的对象,即 IEnumerable ,只有原语。如何告诉 RepoDb 识别对象? -
RepoDB 自动根据类属性自动投影表列,是的,它只是原始类型。如果要处理对象到列的转换,则需要一个属性处理程序。我仍然要模拟这种情况,但是在查看它时,它应该可以正常工作。无论如何,很快就会给你一个反馈