programing

DB 오류를 파악하여 비즈니스 계층에 유용한 정보로 변환하는 방법은 무엇입니까?

css3 2023. 7. 24. 22:45

DB 오류를 파악하여 비즈니스 계층에 유용한 정보로 변환하는 방법은 무엇입니까?

일반적으로 DB에 데이터를 삽입해야 하는데 테이블에 제약이 있어 삽입할 수 없습니다.개발 중인 앱에서는 고유 또는 복합 키 및 기타 메커니즘을 사용하여 일부 비즈니스 규칙(예: "ID 유형 및 번호가 동일한 두 사람이 없습니다." 또는 "XXXX 제품이 이미 등록되었습니다.")이 적용됩니다.DBMS가 오류 메시지(예: ORA-6346 또는 )를 보내는 것은 알고 있지만 .net 4.0에서 이러한 오류를 포착하여 비즈니스 계층에 의미 있는 오류로 변환하는 방법을 모르겠습니다.

예를 들어,나는 DB에 레지스터가 이미 있는지 묻고 그렇지 않으면 데이터를 삽입하는 삽입 메커니즘을 본 적이 있습니다.첫 번째 방법은 매우 비효율적으로 보이기 때문에 쿼리를 사용하고 데이터베이스 제약 조건 위반 오류를 탐지하는 것만으로 이 작업을 수행하고 싶습니다(DB는 오류가 있는 중복에 대해 경고할 수 있습니다).

제가 어떻게 그런 것을 구현할 수 있을까요?

참고: 데이터베이스에서 예외를 감지하고 ORA-xxxx 코드를 사용하여 무슨 일이 일어났는지 파악할 수 있습니다.오류 메시지에 어떤 제약 조건(...의 이름)이 손상되었는지 정확히 기억할 수 없지만 비즈니스 계층 코드에는 제약 조건 이름을 가진 상수가 포함될 수 있으며, 이를 통해 무슨 일이 일어났는지 알 수 있습니다.

여기서 무엇을 해야 하는지는 시스템 아키텍처와 비즈니스 논리 배치에 대한 태도에 따라 결정됩니다.

많은 시스템 설계자들은 데이터베이스를 덤 데이터 저장소로 사용하고 중간/애플리케이션 계층에서 말하는 오류 처리 및 무결성 검사 유형을 구현하는 것을 선호합니다.이는 완벽하게 유효한 접근 방식이며, 특히 비즈니스 로직이 정기적으로 변경되는 경우(데이터베이스 릴리스를 조정하는 것보다 주 중반에 실행 파일을 재배포하는 것이 훨씬 쉬우며), 정기적으로 소규모 릴리스를 필요로 하는 시스템에 적합합니다.

또 다른 접근 방식은 잘 정의된 반영구적 비즈니스 로직을 데이터베이스 계층에 넣는 것입니다.이는 데이터 모델이 더 복잡하고 우수한 DBA를 보유하고 있을 때 특히 강력합니다! ;)

제 개인적인 의견은 엔터프라이즈 데이터베이스는 자체 무결성에 대한 책임을 져야 한다는 것입니다. 따라서 데이터베이스 계층에 논리를 두어 데이터베이스 코드 릴리스에 도입되는 버그에 대한 취약성을 제거하는 것을 선호합니다.따라서 귀사의 구체적인 예에서 저는 분명히 오류를 파악하여 귀사의 애플리케이션 계층에 의미 있는 보고를 할 것입니다.

Oracle은 이름 예외를 사용하여 다양한 유형의 오류를 탐지할 수 있으므로 이러한 예외를 의미 있는 방식으로 응용 프로그램에 적용할 수 있습니다.예:

PROCEDURE test() AS
  b VARCHAR2;
BEGIN

  -- if the following row exists, then DUP_VAL_ON_INDEX will be thrown 
  -- (assuming there is a primary key constraint)        

  INSERT INTO table(a,b,c)
  VALUES(1,2,3);  

  -- if there is no matching record, NO_DATA_FOUND will be thrown

  SELECT a
  INTO b
  FROM TABLE
  WHERE c = 'blah';  

EXCEPTION   -- both types of exception can be caught and embellished 
  WHEN DUP_VAL_ON_INDEX THEN
    raise_application_error(-20570, 'Attempted to insert a duplicate value', TRUE);
  WHEN NO_DATA_FOUND THEN
    raise_application_error(-20571, 'No matching row in table for value:' || 'blah', TRUE);
  WHEN OTHERS THEN
  rollback
END test;

자세한 내용은 여기에서 확인할 수 있습니다. http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14261/errors.htm

이게 도움이 되길..

몇 가지 접근 방식이 있습니다. 제가 할 일은 대체로 다음과 같습니다.

  1. 오류가 DB 호출에서 관리되는 코드로 다시 거품이 일게 합니다.
  2. 구성 요소를 사용하여 SQL에서 제공하는 오류 메시지를 검토하고 해당 "사용자/비즈니스 계층에 적합한" 메시지를 식별합니다.

오류 처리는 저장된 프로세스 내에서 수행될 수 있지만 비즈니스 계층이 절대 알지 못하는 것을 제공하고자 하는 경우에는 시나리오와 정확히 맞지 않는다는 Mellamokb의 의견에 동의합니다.

#2의 경우, MS Enterprise Libraries에는 구성을 통해 그런 종류의 것에 접근할 수 있는 오류 처리 블록이 있습니다. 그렇지 않으면 접근할 수 있습니다.

저는 최근에 같은 생각을 하고 있었습니다.나는 메시지를 다음에서 가져오는 확장 방법을 만들었습니다.SqlException그리고 정규식을 사용하여 오류 메시지 및 문자열에서 유용한 정보를 추출하는 최종 사용자에게 더 유용한 정보로 변환합니다.새 메시지에 해당 정보를 넣을 형식입니다.

두 번째 사전을 사용하여 정규식에서 찾은 제약 조건 이름을 찾아 위반된 제약 조건에 대한 영어 설명으로 변환했습니다.

다음 SQL 오류 메시지:

Violation of UNIQUE KEY constraint 'uniq_ticket'. Cannot insert duplicate key in object 'dbo.TicketHeader'. The statement has been terminated.

다음 결과를 반환합니다.

Save to table dbo.TicketHeader failed: Ticket number must be unique.

오라클에서 보낸 예외에 대해서도 매우 유사하게 작동할 수 있을 것으로 예상됩니다.

    public static class SqlExceptionExtension
    {
        private static readonly Dictionary<string, string> Messages;
        private static readonly Dictionary<string, string> Constraints;
        static SqlExceptionExtension()
        {
            Messages = new Dictionary<string, string> {{@"Violation of UNIQUE KEY constraint '(?<Constraint>.*)'. Cannot insert duplicate key in object '(.*)'. The statement has been terminated.", "Save to table {2} failed: {0}"}};
            Constraints = new Dictionary<string, string> { { "uniq_ticket", "Ticket number must be unique." } };
        }
        public static string BusinessLayerMessage(this Exception e)
        {
            foreach(var reg in Messages.Keys)
            {
                var match = Regex.Match(e.Message, reg);
                if (match.Success)
                {
                    string friendlyConstraint = "";
                    if (match.Groups["Constraint"] != null)
                    {
                        friendlyConstraint = Constraints[match.Groups["Constraint"].Value] ??
                                             match.Groups["Constraint"].Value;
                    }
                    var groups = match.Groups.Cast<Group>().Select(x => x.Value);
                    var strings = new [] {friendlyConstraint};
                    return String.Format(Messages[reg], strings.Concat(groups).ToArray());
                }
            }
            return "Unexpected Database error.";
        }
    }
}

저는 당신이 이것을 개인적으로 할 수 있다고 생각합니다.SqlError또는OracleError보다 신뢰할 수 있는 결과를 위해 예외에 포함된 s는 개념 증명에 불과합니다.

제가 알고 있고 사용해 본 방법은 직접 동일한 유효성 검사를 수행하고 유용한 오류 코드를 응용 프로그램에 반환하는 것입니다.따라서 예를 들어 레코드를 데이터베이스에 삽입하는 저장 프로시저가 있는 경우 제약 조건이 모두 충족되는지 여부도 확인해야 하며 그렇지 않은 경우 적절한 오류 코드를 반환해야 합니다.

(pseudo-sql)
function create-user
    @username, @password, @name, @email
as

if @username already exists return 1  --duplicate username
if @email already exists return 2   --duplicate email

insert user values (@username, @password, @name, @email)
return 0   -- success

영감을 찾고 있다면 NHibernate가 이를 어떻게 처리하는지 살펴보세요.ISQLExceptionConverter인터페이스여기에서 구현 예를 볼 수 있습니다.

언급URL : https://stackoverflow.com/questions/7395943/how-to-catch-db-errors-and-translate-them-into-meaningful-information-for-the-bu