使用存储过程和反射获取从多个数据表所需信息

本文介绍了一种通过存储过程结合反射技术实现多表联查的方法,特别适用于需要从多个表中获取复杂数据并展示在界面上的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文介绍如何使用存储过程和读取范式化数据库获取所需信息的技术,使用到的技术有:存储过程,反射。此技巧适用于与多处连表(大量JOIN)的场景。 对于单表操作,建议使用UnitOfWork+Repository的设计模式的EF操作方法,该方法并非本文描述重点。

关键字 存储过程;反射;范式;连表;


场景需要读取收据信息

收据Model  DTO定义如下

public class ApplicantExamReceiptModel
    {
        public ApplicantExamReceiptModel()
        {
            //Claims = new List<ClaimModel>();            
        }

        public PaymentTypeEnum PaymentTypeMethod { get; set; }

        public int ApplicantExamId { get; set; }

        public string FirstName { get; set; }

        public string MiddleName { get; set; }

        public string LastName { get; set; }

        public string ExamNumber { get; set; }

        public string ExamTitle { get; set; }

        public string PhoneNumber { get; set; }

        public string Email { get; set; }

        public string AddressLine { get; set; }

        public string CityTown { get; set; }

        public string StateProvince { get; set; }

        public string PostalCode { get; set; }

        public string Country { get; set; }

        public DateTime? BirtDate { get; set; }

        public string BirtDateStr { get; set; }

        public string Gender { get; set; }

        public List<ApplicantClaimModel> ApplicantClaims { get; set; }

        public string RecruitmentSource { get; set; }

        public DateTime? PaymentStatusDate { get; set; }

        public DateTime? PaidOn { get; set; }

        public string PaymentStatusDateString { get; set; }

        public string ExamPaymentMethod { get; set; }

        public int ExamPaymentMethodId { get; set; }

        public string PaymentStatus { get; set; }

        public string PaymentDescriptor { get; set; }

        public decimal? ExamFee { get; set; }

        public string IsHispanicLatino { get; set; }

        public string Ethnicity { get; set; }

        public string PaymentReference { get; set; }

        public bool? IsHistorical { get; set; }

}

信息源表截图如下:



该表中由于使用了部分外键Gender为例,字段中存储1,2, 实际内容存储在Gender表中,需要链表读取

存储过程如下:

USE [OASysLite]
GO
/****** Object:  StoredProcedure [Applicant].[usp_GetApplicantExamInfo]    Script Date: 3/15/2017 11:55:21 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [Applicant].[usp_GetApplicantExamInfo]
	@applicantexamid int, @requestid int
AS

Begin 
	if(@requestid=1)-- get all receipt info for specific applicant exam 
	  BEGIN
	      SELECT AED.ApplicantExamId, AED.FirstName,AED.MiddleName,AED.LastName, AED.PhoneNumber,AED.Email,
		  AED.AddressLine, AED.CityTown, AED.StateProvince, AED.StateProvince, AED.PostalCode, AED.Country,
		  AED.BirthDate,CG.Name [Gender], AED.HispanicLatinoId,EE.ExamNumber, EE.Title [ExamTitle],CR.Name [RecruitmentSource],
		  PM.Name [ExamPaymentMethod],PM.PaymentMethodId [ExamPaymentMethodId],AP.ExamFee,AP.PaidOn,AP.PaymentReference,
		  HL.Name [IsHispanicLatino], CE.Name [Ethnicity]
		  FROM [OASysLite].[Applicant].[ApplicantExamDemographic] AED
		  LEFT JOIN [OASysLite].[Config].[Gender] CG ON AED.GenderId = CG.GenderId
		  LEFT JOIN [OASysLite].[Applicant].[ApplicantExam] AE ON AE.ApplicantExamId = AED.ApplicantExamId
		  LEFT JOIN [OASysLite].[ExamSetup].[Exam] EE ON EE.ExamId = AE.ExamId
		  LEFT JOIN [OASysLite].[Applicant].[ApplicantPayment] AP ON AP.ApplicantExamId = AED.ApplicantExamId
		  LEFT JOIN [OASysLite].[ExamSetup].[ExamPaymentMethod] EPM ON EPM.ExamPaymentMethodId = AP.ExamPaymentMethodId
		  LEFT JOIN [OASysLite].[Config].[PaymentMethod] PM ON PM.PaymentMethodId = EPM.PaymentMethodId
		  LEFT JOIN [OASysLite].[Config].[PaymentTransactionFee] CPTF ON PM.PaymentMethodId=CPTF.PaymentMethodId
		  LEFT JOIN [OASysLite].[Config].[HispanicLatino] HL ON HL.HispanicLatinoId=AED.HispanicLatinoId
		  LEFT JOIN [OASysLite].[Config].[Ethnicity] CE ON CE.EthnicityId=AED.EthnicityId
		  LEFT JOIN [Config].[RecruitmentSource] CR ON CR.RecruitmentSourceId = AE.RecruitmentSourceId
		  WHERE AE.ApplicantExamId = @applicantexamid
	  END

	ELSE IF(@requestid = 4) -- get claims
		BEGIN
			SELECT AC.ApplicantClaimId, AC.ApplicantExamId, AC.ProfileId, AC.ClaimTypeId,AC.IsConfirmed, CT.Name
			FROM [OASysLite].[Applicant].[ApplicantClaim] AC
			LEFT JOIN [OASysLite].[Config].[ClaimType] CT ON CT.ClaimTypeId = AC.ClaimTypeId
			WHERE AC.ApplicantExamId = @applicantexamid
		END

	ELSE IF(@requestid = 6) -- QIE Appeal Document
		BEGIN
			SELECT OAAED.ApplicantExamId,OAAED.FirstName,OAAED.MiddleName,OAAED.LastName, OAAED.AddressLine,OEE.ExamNumber,
			OEE.Title [ExamTitle], OAP.SSN
			FROM [OASysLite].[Applicant].[ApplicantExamDemographic] OAAED
			LEFT JOIN [OASysLite].[Applicant].[ApplicantExam] OAA ON OAA.ApplicantExamID=OAAED.ApplicantExamID
			LEFT JOIN [OASysLite].[ExamSetup].[Exam] OEE ON OEE.ExamId=OAA.ExamId
			LEFT JOIN [OASysLite].[Applicant].[Profile] OAP ON OAA.ProfileId = OAP.ProfileId
			WHERE OAA.ApplicantExamId = @applicantexamid
		END

	else if(@requestid=7)--QIE QualificationOption
	    BEGIN
			   SELECT AQO.ApplicantExamId,OEEQO.ExamPartSectionId,OEEQO.ExamQualificationOptionId,OEEQO.Name,AQO.ApplicantAnswer [IsChecked]
			   FROM [OASysLite].[ExamSetup].[ExamQualificationOption] OEEQO
			   join ApplicantQIE.ApplicantExamQualificationOption AQO ON AQO.ExamQualificationOptionId=OEEQO.ExamQualificationOptionId
			   WHERE ExamPartSectionId in  (select distinct(oeeps.ExamPartSectionId)
			   from [OASysLite].[Applicant].[ApplicantExam] oaa
			   left join [OASysLite].[ExamSetup].[ExamPart] oee on oee.ExamId = oaa.ExamId
			   left join [OASysLite].[ExamSetup].[ExamPartSection] oeeps on oeeps.ExamPartId=oee.ExamPartId
			   where oaa.ApplicantExamId=@applicantexamid)
		END

	else if(@requestid=8)--QIE QualificationOption
	    BEGIN
				SELECT  OEE.ExamCityEmploymentId,OEE.ExamPartSectionId,OEE.Name,ACE.ApplicantAnswer [IsChecked]
				FROM [OASysLite].[ExamSetup].[ExamCityEmployment] OEE
				join ApplicantQIE.ApplicantExamCityEmployment ACE ON ACE.ExamCityEmploymentId=OEE.ExamCityEmploymentId
				WHERE ExamPartSectionId in  (select distinct(oeeps.ExamPartSectionId)
				from [OASysLite].[Applicant].[ApplicantExam] oaa
				left join [OASysLite].[ExamSetup].[ExamPart] oee on oee.ExamId = oaa.ExamId
				left join [OASysLite].[ExamSetup].[ExamPartSection] oeeps on oeeps.ExamPartId=oee.ExamPartId
				where oaa.ApplicantExamId=@applicantexamid)
		END
END

该存储过程中,@requestid=1时为本案例需要关注的内容执行该存储过程,结果如下图所示

注意事项  存储过程选出来的结果必须与DTO Model中的字段名称保持一致

 

C#代码

存储过程完成了接下来使用代码来读取该内容以获取到存储过程执行结果

private List<T> ExecuteCommand<T>(int applicantexamid,  int requestid = 0) where T : new()
        {
            List<T> res = new List<T>();

            using (UnitOfWork unitOfWork = new UnitOfWork())
            {
                SqlConnection dbcon = new SqlConnection(unitOfWork.Context.Database.Connection.ConnectionString);
                try
                {
                    SqlCommand cmd = new SqlCommand();
                    cmd.Connection = dbcon;
                    cmd.CommandType = System.Data.CommandType.StoredProcedure;
                    cmd.CommandText = "[Applicant].[usp_GetApplicantExamInfo]";
                    cmd.Parameters.AddWithValue("@applicantexamid", applicantexamid);
                    cmd.Parameters.AddWithValue("@requestid", requestid);

                    dbcon.Open();

                    SqlDataReader oDr = cmd.ExecuteReader();
                    while (oDr.Read())
                    {
                        T t = new T();

                        for (int inc = 0; inc < oDr.FieldCount; inc++)
                        {
                            Type type = t.GetType();
                            PropertyInfo prop = type.GetProperty(oDr.GetName(inc));
                            if (prop != null)
                            {
                                var val = oDr.GetValue(inc);
                                if (val != null && !val.ToString().Equals(""))
                                {
                                    var targetType = prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))
                                        ? Nullable.GetUnderlyingType(prop.PropertyType) : prop.PropertyType;
                                    val = Convert.ChangeType(val, targetType);
                                    prop.SetValue(t, val, null);
                                }
                            }
                        }
                        res.Add(t);
                    }

                    oDr.Close();
                }
                catch (Exception ex)
                {
                    throw;
                }
                finally
                {
                    dbcon.Close();
                }
            }

            return res;
        }

使用代码如下

ApplicantExamReceiptModel oResult = new ApplicantExamReceiptModel();

            var ApplicantExamReceiptModelList = ExecuteCommand<ApplicantExamReceiptModel>(applicantExamId,  (int)ApplicantExamRequestType.Receipt);


小结

至此就已经从多个表格获得了所需的信息。任何方法都有适用场景和非适用场景,本方法适用于多处连表,并且需要将数据读取出来并显示到界面的操作。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值