0

以下のコードを実行すると、例外が発生します。どこが間違っていますか?

特に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();
                    }
                }
            }

Visit テーブルに対応するドメイン エンティティ:

    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();
        }

    }

Visit テーブルと ChiefComplaint テーブル:

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);
        }
    }

私のデータ層プロジェクトには、構成要件を実装し、以下のように ConfigureServices で呼び出される DependencyInjection.cs クラスがあります。ここで、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"));
        }
4

1 に答える 1

0

ライブラリの最新バージョンは不変クラスをサポートしており、ctor フィールドがデータ リーダー列と一致する必要があります。

以下は私たちの推奨事項です。

クラスのctorに引数が含まれVisitていてはなりません。chiefComplaints

public Visit(long id, DateTime dateOfService) : base(id)
{
    this.DateOfService = dateOfService;
}

次に、ローカル変数のチーフ クレームを設定するメソッドを追加します (または、以下のように書き込み可能なパブリック プロパティにします)。

public List<ChiefComplaint> ChiefComplaints { get; set; }

抽出中に、プロパティを設定するだけです (以下を参照)。

var v = extractor.Extract<Visit>().FirstOrDefault();
var cc = extractor.Extract<ChiefComplaint>().AsList();
return new Visit(v.Id, v.DateOfService)
{
     ChiefComplaints = cc.AsList()
};

ただし、この ctor 構造を改善するために、GH ページに問題を追加しました。

于 2021-02-06T13:37:00.550 に答える