애플리케이션에서 사용자 정의 필드를 지원하는 디자인 패턴은 무엇입니까?
우리는 상용 응용 프로그램을 개발합니다. 고객이 사용자 정의 필드 지원을 요청하고 있습니다. 예를 들어, 고객 양식에 필드를 추가하려고합니다.
필드 값과 필드에 대한 메타 데이터를 저장하는 알려진 디자인 패턴은 무엇입니까?
지금은 다음 옵션이 표시됩니다.
옵션 1 : varchar 유형의 Field1, Field2, Field3, Field4 열을 고객 테이블에 추가합니다.
옵션 2 : 고객 테이블에 XML 유형의 단일 열을 추가하고 사용자 정의 필드의 값을 xml에 저장합니다.
옵션 3 : varchar 유형의 열이있는 CustomerCustomFieldValue 테이블을 추가하고 해당 열에 값을 저장합니다. 이 테이블에는 CustomerID, CustomFieldID도 있습니다.
CustomerID, CustomFieldID, Value
10001, 1001, '02/12/2009 8:00 AM'
10001, 1002, '18.26'
10002, 1001, '01/12/2009 8:00 AM'
10002, 1002, '50.26'
CustomFieldID는 CustomFieldID, FieldName, FieldValueTypeID 열이있는 CustomField라는 다른 테이블의 ID입니다.
옵션 4 : 가능한 각 값 유형의 열이있는 CustomerCustomFieldValue 테이블을 추가하고 오른쪽 열에 값을 저장합니다. # 3과 유사하지만 필드 값은 강력한 유형의 열을 사용하여 저장됩니다.
CustomerID, CustomFieldID, DateValue, StringValue, NumericValue
10001, 1001, 02/12/2009 8:00 AM, null, null
10001, 1002, null, null, 18.26
10002, 1001, 01/12/2009 8:00 AM, null, null
10002, 1002, null, null, 50.26
옵션 5 : 옵션 3 및 4는 단일 개념 (고객)에 특정한 표를 사용합니다. 우리 고객들은 다른 형태의 커스텀 필드도 요구하고 있습니다. 대신 시스템 전체의 맞춤형 필드 스토리지 시스템을 가져야합니까? 따라서 CustomerCustomFieldValue, EmployeeCustomFieldValue, InvoiceCustomFieldValue와 같은 여러 테이블을 사용하는 대신 CustomFieldValue라는 단일 테이블이 있습니까? 나에게는 더 우아해 보이지만 성능 병목 현상이 발생하지 않습니까?
이러한 접근 방식을 사용한 적이 있습니까? 성공 했습니까? 어떤 접근 방식을 선택 하시겠습니까? 고려해야 할 다른 접근 방식을 알고 있습니까?
또한 내 고객은 사용자 정의 필드가 다른 테이블의 데이터를 참조 할 수 있기를 원합니다. 예를 들어 고객은 "즐겨 찾기 결제 방법"필드를 고객에게 추가 할 수 있습니다. 지불 방법은 시스템의 다른 곳에서 정의됩니다. 그것은 그림에서 "외래 키"의 주제를 가져옵니다. 사용자 정의 필드 테이블에 저장된 값이 유효한 값인지 확인하기 위해 제약 조건을 만들어야합니까?
감사
======================
2009 년 7 월 27 일 수정 :
귀하의 답변에 감사드립니다. 이제 접근 방식 목록이 상당히 포괄적 인 것 같습니다. 옵션 2 (단일 XML 열)를 선택했습니다. 지금은 구현하기 가장 쉬웠습니다. 내 요구 사항이 더 복잡해지고 지원할 사용자 정의 필드 수가 더 많아 지므로보다 강력하게 정의 된 접근 방식으로 재구성해야 할 것입니다.
옵션 3, 4 또는 5가 가장 적절할 것 같다는 아래의 포스터에 동의합니다. 그러나 제안 된 각 구현에는 장점과 비용이 있습니다. 특정 요구 사항에 일치시켜 하나를 선택하는 것이 좋습니다. 예를 들면 :
- 옵션 1 장점 : 구현이 빠릅니다. 사용자 지정 필드 (검색, 정렬)에 대한 DB 작업을 허용합니다.
옵션 1 단점 : 사용자 지정 필드는 일반이므로 강력한 형식의 필드가 없습니다. 데이터베이스 테이블은 비효율적이며 크기 측면에서 사용되지 않는 많은 외부 필드가 있습니다. 허용되는 사용자 정의 필드의 수를 예상해야합니다. - 옵션 2 장점 : 구현이 빠릅니다. 유연하며 임의의 수와 유형의 사용자 정의 필드를 허용합니다.
옵션 2 단점 : 사용자 지정 필드에서 가능한 DB 작업이 없습니다. 나중에 사용자 정의 필드를 표시하거나 고객별로 데이터를 약간만 조작하는 경우에만이 방법이 가장 좋습니다. - 옵션 3 장점 : 유연하고 효율적입니다. DB 작업을 수행 할 수 있지만 낭비되는 공간을 줄이기 위해 데이터가 다소 정규화됩니다. 유형 또는 소스 정보를 지정하는 데 사용할 수있는 추가 열을 추가하라는 unknown (google)의 제안에 동의합니다. 옵션 3 단점 : 개발 시간이 약간 증가하고 쿼리가 복잡해 지지만 실제로는 단점이 많지 않습니다.
- 옵션 4는 입력 한 데이터를 DB 수준에서 작동 할 수 있다는 점을 제외하면 옵션 3과 동일합니다. 옵션 3의 링크 테이블에 유형 정보를 추가하면 애플리케이션 수준에서 더 많은 작업을 수행 할 수 있지만 예를 들어 DB는 비교 또는 정렬을 수행 할 수 없습니다. 3과 4 사이의 선택은이 요구 사항에 따라 다릅니다.
- 옵션 5는 3 또는 4와 동일하지만 솔루션을 다양한 테이블에 적용하는 데 훨씬 더 유연합니다. 이 경우 비용은이 테이블의 크기가 훨씬 더 커질 것입니다. 사용자 지정 필드를 얻기 위해 많은 비용이 많이 드는 조인 작업을 수행하는 경우이 솔루션은 제대로 확장되지 않을 수 있습니다.
PS 아래에서 언급 한 바와 같이 "디자인 패턴"이라는 용어는 일반적으로 객체 지향 프로그래밍을 나타냅니다. 데이터베이스 디자인 문제에 대한 솔루션을 찾고 있습니다. 즉, 디자인 패턴과 관련된 대부분의 조언이 적용되지 않습니다.
응용 프로그램 코드에 관한 한 확실하지 않습니다. 사용자 지정 필드 는 데이터베이스 의 EAV 모델 에서 큰 이점을 얻는다는 것을 알고 있습니다.
아래 설명에 따르면이 모델에서 할 수있는 가장 큰 실수는 외래 키를 넣는 것입니다. 절대로 FriendID 또는 TypeID와 같은 것을이 모델에 넣지 마십시오. 이 모델을 일반적인 관계형 모델과 함께 사용하고 외래 키 필드를 테이블 열에 있어야합니다.
두 번째 중요한 실수는 모든 요소와 함께보고해야하는 데이터를이 모델에 배치하는 것입니다. 예를 들어이 모델에 사용자 이름과 같은 것을 입력하면 사용자에게 액세스하고 싶을 때마다 사용자 이름을 알아야 할 때 조인에 직접 참여했거나 2n 쿼리에서 n은보고있는 사용자 수를 의미합니다. . 일반적으로 모든 User 요소에 대해 Username 속성이 필요하다고 생각할 때이 속성도 테이블 열에 남아 있어야한다는 것이 분명해집니다.
그러나이 모델을 사용자 지정 사용자 필드와 함께 사용하는 경우에는 괜찮습니다. 사용자가 관계형 데이터를 입력하고 EAV 모델이 검색에 크게 해를 끼치 지 않는 많은 상황을 상상할 수 없습니다.
마지막으로, 여기에서 데이터를 결합하여 멋진 멋진 레코드 세트를 얻으려고하지 마십시오. 원본 레코드를 가져온 다음 엔터티에 대한 레코드 집합을 가져옵니다. 테이블에 참여하고 싶은 마음이 든다면 위에서 언급 한 두 번째 실수를했을 것입니다.
객체 지향 언어로 개발하는 경우 여기서는 적응 형 객체 모델 에 대해 이야기하고 있습니다. oo 언어로 구현하는 방법에 대한 기사가 많이 있지만 데이터 저장소 측을 설계하는 방법에 대한 정보는 많지 않습니다.
제가 일하는 회사에서는 관계형 데이터베이스를 사용하여 AOM 데이터를 저장하여 문제를 해결했습니다. 사람, 네트워크 장치, 회사 등과 같은 도메인의 모든 다른 "엔티티"를 표시하기위한 중앙 엔터티 테이블이 있습니다. 실제 "양식 필드"를 입력 된 데이터 테이블에 저장하므로 하나의 테이블이 있습니다. 문자열, 하나는 날짜 등입니다. 모든 데이터 테이블에는 엔티티 테이블을 가리키는 외래 키가 있습니다. 또한 유형 측을 표시하기위한 테이블이 필요합니다. 즉, 특정 엔티티가 가질 수있는 속성 (양식 필드)의 종류와이 정보는 데이터 테이블의 데이터를 해석하는 데 사용됩니다.
우리 솔루션의 장점은 엔터티 간의 참조, 다중 값 등을 포함하여 코드 변경없이 모든 것을 모델링 할 수 있다는 것입니다. 필드에 비즈니스 규칙 및 유효성 검사를 추가 할 수도 있으며 모든 형식에서 재사용 할 수 있습니다. 단점은 프로그래밍 모델이 이해하기 쉽지 않고 일반적인 DB 설계보다 쿼리 성능이 나빠진다는 것입니다. 관계형 데이터베이스 이외의 다른 솔루션이 AOM에 더 좋고 쉬웠을 수 있습니다.
작동하는 데이터 저장소로 좋은 AOM을 구축하는 것은 많은 작업이며 고도로 숙련 된 개발자가 없으면 권장하지 않습니다. 언젠가는 이러한 요구 사항에 대한 OS 솔루션이있을 것입니다.
사용자 정의 필드는 이전에 논의되었습니다.
- SQL 데이터베이스에서 사용자 정의 사용자 정의 필드를 어떻게 만들고 저장합니까?
To add custom/user-defined fields feature or not?- What architecture can I use to handle a shopping cart where each product requries different attributes to be saved
Something like Option 3 is the way to go and i have used this method previously. Create a single table to define additional properties and their corresponding values. This would be a 1-N relationship between your Customer and CustomerCustomField table (respectively). Your second question regarding defining relationships with custom properties would be something to think about. The first thing that comes to mind is adding a DataSource field, which would contain the table to which the property value is bound to. So essentially your CustomerCustomField would look like:
- CustomerId
- Property
- Value
- ValueDataSource (nullable)
This should allow you to either bind to a specific data structure or simply allow you to specify unbound values. You can further normalize this model, but something like this could work and should be easy enough to handle in code.
Option 4 or 5 would be my choice. If your data is important, I wouldn't go tossing away your type information with Option 3. (You might try to implement full type-checking yourself, but it's a pretty big job, and the database engine already does it for you.)
Some thoughts:
- Make sure your
CustomFields
has aDataType
column.- Use a UDF-based check constraint on
CustomFieldValues
to ensure that the column specified byCustomFields.DataType
is non-null. - You'll also want a standard check constraint to make sure you have exactly one non-null value.
- Use a UDF-based check constraint on
- Regarding foreign keys, I would model these as a separate
DataType
.- Each potential cross-table reference would require its own column. This is good, because it maintains referential integrity.
- You would have to support these relationships in application code anyway, so the fact that they are hard-coded in the database does not actually limit functionality.
- This will also jive well with your ORM, if you're using one.
- For Option 5, use intermediary tables to model the relationships.
- You would still have a
CustomerCustomFieldValue
, but instead with onlyCustomerID
andCustomFieldValueID
columns.
- You would still have a
- Think long and hard about your constraints every step of the way. This is tricky stuff, and one misstep can cause utter havok down the line.
I am using this in an application currently in development. There haven't been any problems yet, but EAV designs still scare the daylights out of me. Just be careful.
As an aside, XML may also be a good choice. I don't know as much about it from direct experience, but it was one of the options I considered when starting the data design, and it looked pretty promising.
if those 'extra' fields are incidental and don't care to do searches on them, I usually go for option 2 (but like JSON better than XML). If there's going to be searches on custom fields, option 3 isn't hard to do, and usually the SQL optimizer can get reasonable performance out of it.
I am currently working on a project with this same problem, and I have chosen to use option 3, but I added a FieldType field and a ListSource field in case the FieldType="list". The ListSource field could be a query, an sql view, a function name, or something that results in a list of options for the list. The biggest problem with trying to store fields like this in my situation is that this field list can change, and the users are allowed to edit the data later. So what to do if the field list has changed and they go to edit. My solution to that scenario was to allow editing only if the list hasn't changed and to display read-only data if it has.
'Nice programing' 카테고리의 다른 글
AttributeSet은 무엇이며 어떻게 사용할 수 있습니까? (0) | 2020.10.30 |
---|---|
Wii 프로그래밍을위한 튜토리얼 (0) | 2020.10.30 |
성공, 오류 및 완료 대 .done (), .fail () 및 always ()를 사용하는 jQuery ajax () (0) | 2020.10.30 |
모델 상태를 Angular.js에 저장해야하는 위치 (0) | 2020.10.30 |
JSONP를 반환하는 ASP.net MVC (0) | 2020.10.30 |