Dapper.Net - QueryMultiple использовать с хранимой процедурой, возвращающей несколько результатов - PullRequest
0 голосов
/ 27 апреля 2018

Я новичок в Dapper.Net и пытался написать свой собственный микро ORM, но после некоторого обзора почувствовал, что Dapper может выполнить мои требования.

Я был очень близок к тому, чтобы понять это правильно, но все еще не там. Я думаю, что моя текущая реализация не так быстро, как родной Dapper. Пожалуйста, помогите и спасибо!

Pocos

public class CustomerCollections
{
    public decimal CifNo { get; set; }
    public string StatusCode { get; set; }
    public decimal TotalPastDue { get; set; }
    public int PaymentsReturned { get; set; }
    public int DaysPastDue { get; set; }
    public List<CollectionPayment> CollectionPayments { get; set; }

}

public class CollectionPayment
{
    public decimal CifNo { get; set; }
    public decimal AcctRefNo { get; set; }
    public decimal PaymentReferenceNumber { get; set; }
    public decimal PaymentAmount { get; set; }
    public DateTime DueDate { get; set; }
    public DateTime NsfDate { get; set; }
    public CollectionPaymentDetail PaymentDetail { get; set; }
}

public class CollectionPaymentDetail
{
    public decimal PaymentReferenceNumber { get; set; }
    public string PaymentMethodType { get; set; }
    public decimal PaymentAmount { get; set; }
    public decimal InterestAmount { get; set; }
    public decimal PrincipalAmount { get; set; }
    public DateTime DueDate { get; set; }
    public DateTime NsfDate { get; set; }
    public string ReturnCode { get; set; }
    public string AgentUser { get; set; }

}

Вот моя хранимая процедура

ALTER PROCEDURE ULPS.sp_GetCollections
(
    @cifno INT
)
AS
BEGIN

SET NOCOUNT ON;

--Past Due Header Info
SELECT l.cifno AS Cifno
    --, l.acctrefno
    , c.status_code AS StatusCode
    , CASE 
        WHEN LOWER(c.status_code) = 'past due' THEN SUM(l.total_past_due_balance)
        ELSE 0
      END
      AS TotalPastDue
     , SUM(p.num_payments_returned) AS PaymentsReturned
     , CAST(SUM(d.days_past_due) AS INT) AS DaysPastDue
FROM dbo.loanacct l
OUTER APPLY (
    SELECT h.acctrefno, COUNT(tc.transaction_description) AS num_payments_returned  FROM dbo.loanacct_trans_history h
    INNER JOIN dbo.loan_transaction_codes tc
    ON tc.transaction_code = h.transaction_code AND LOWER(tc.transaction_description) = 'nsf fee'
    GROUP BY h.acctrefno
) AS p
LEFT JOIN dbo.loanacct_statuses s
    ON s.acctrefno = l.acctrefno
INNER JOIN dbo.loan_status_codes c
    ON c.status_code_no = s.status_code_no
OUTER APPLY (
    SELECT cifno, acctrefno, days_past_due, open_date FROM dbo.loanacct
) AS d
WHERE p.acctrefno = l.acctrefno
    AND (LOWER(c.status_code) = 'write-off' OR LOWER(c.status_code) = 'past due')
    AND l.status_code_no = 0 --ACTIVE ONLY
    AND l.cifno = @cifno
    AND d.acctrefno = l.acctrefno
    AND d.cifno = @cifno
GROUP BY l.cifno
    , c.status_code

--Past Due Loan List
CREATE TABLE #PastDueLoanList (
    Cifno NUMERIC(10,0)
    , AcctRefNo NUMERIC(10,0)
    , PaymentReferenceNumber NUMERIC(9,0)
    , PaymentAmount NUMERIC(12,2)
    , DueDate DATETIME
    , NsfDate DATETIME
) 
INSERT INTO #PastDueLoanList
SELECT l.cifno AS Cifno 
    , h.acctrefno AS AcctRefNo
    , h.payment_reference_no AS PaymentReferenceNumber
    , SUM(h.payment_amount) AS PaymentAmount
    , h.date_due AS DueDate
    , h.nsf_date AS NsfDate
FROM dbo.loanacct l
INNER JOIN dbo.loanacct_payment_history h
    ON h.acctrefno = l.acctrefno and h.nsf_flag = 1 and h.payment_number <> 0
WHERE l.cifno = @cifno
GROUP BY l.cifno
    , h.acctrefno
    , h.payment_reference_no
    , h.transaction_reference_no
    , h.payment_number
    , h.date_due
    , h.nsf_date 

SELECT * FROM #PastDueLoanList

--Past Due Payment Details
SELECT h.acctrefno AS AcctRefNo
    , h.payment_reference_no AS PaymentReferenceNumber
    , m.payment_method_code AS PaymentMethodType
    , SUM(CASE WHEN h.transaction_code = 0 THEN payment_amount ELSE 0 END) AS PaymentAmount
    , SUM(CASE WHEN h.transaction_code = 206 THEN payment_amount ELSE 0 END) AS InterestAmount
    , SUM(CASE WHEN h.transaction_code = 204 THEN payment_amount ELSE 0 END) AS PrincipalAmount
    , MAX(h.date_due) AS DueDate
    , MAX(h.nsf_date) AS NsfDate
    , 'n/a' AS ReturnCode
    , 'unknown, user' AS AgentUser
FROM dbo.loanacct l (NOLOCK)
INNER JOIN #PastDueLoanList tmp
    ON tmp.AcctRefNo = l.acctrefno
INNER JOIN dbo.loanacct_payment_history h (NOLOCK)
    ON h.acctrefno = l.acctrefno and h.nsf_flag = 1
INNER JOIN dbo.loan_payment_method m (NOLOCK)
    ON m.payment_method_no = h.payment_method_no
GROUP BY h.acctrefno
    , h.payment_reference_no
    , m.payment_method_code
END
GO

Это работает, но не по Дапперу.

public async Task<CustomerCollections> GetCustomerCollections(decimal cifno)
{
    var collections = new CustomerCollections();
    using (var multi = await DbContext.NativeContext().QueryMultipleAsync("ULPS.sp_GetCollections", new { cifno }, commandType: CommandType.StoredProcedure))
    {
        collections = await multi.ReadFirstOrDefaultAsync<CustomerCollections>();
        collections.CollectionPayments = multi.Read<CollectionPayment>().ToList();
        var details = multi.Read<CollectionPaymentDetail>().ToList();
        collections.CollectionPayments.ForEach(c =>
        {
            details.ForEach(d =>
            {
                if (c.PaymentReferenceNumber == d.PaymentReferenceNumber)
                    c.PaymentDetail = d;
            });
        });
    }
    return collections;
}

1 Ответ

0 голосов
/ 30 апреля 2018

Я бы вернул набор результатов в виде JSON (если вы используете версию SQL Server, которая его поддерживает, например, SQL Server 2016 или более позднюю версию или Azure SQL), а затем использовал бы функцию «Пользовательская обработка типов», чтобы десериализовать JSON в ваш комплекс. объект:

https://medium.com/dapper-net/custom-type-handling-4b447b97c620

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...