Database design for polymorphic data

I have an application that needs to log communications with users over several different mediums: Email, SMS, Voice, Website Announcements, etc.. in a traditional database.

I have considered 3 approaches to modeling these different types of data:

  1. Single Table Inheritance:
    Store them all together in a single table (i.e., comm_message) with discriminator field of some sort to indicate the type of communications (e.g. message_type). This means that some fields in the table won’t be used for each type–and it means that the same message may be duplicated in several different rows in the table (if the message is sent via more than one medium).

  2. Message “has” transports
    Have a message table (comm_message) and then transports table (comm_transports) with the various different mediums of communication. A many-to-many relationship between messages and transports would mean one row for each message in the message table–but that row might have several different transports. If additional specific information is needed for a particular transport, it could be in it’s own table (i.e. comm_sms, comm_email, etc..) that is linked off the many-to-many table. I.e., a “has-a” approach.

  3. Class Table Inheritance:
    Create a base message table (comm_message) and then another table for each medium with fields specific to it (inheritance). My ORM (LLBLGen) would facilitate this approach by using shared PKs for the different tables. In this approach there would be a row in the base table (comm_message), plus rows in each of the related tables for each transport (comm_email, comm_sms, etc.) but there would be no many-to-many relationship. Rather the records across different tables would share the same PK (1-1). This would be more of an “is-a” approach.

Context: This is a medium sized application (around 100 tables) that I’ll be maintaining for many years–so I’d like to get this “right”. I’ll often need to present all the communications info together in the UI in a grid, reports, etc..

Which should I use? Why?

2

Follow composition over inheritance as composition lends itself well to relational databases.

Say you want to get all short messages:

SELECT * FROM Message INNER JOIN ShortMessage ON ShortMessage.message = Message.id

Say you want to get all short messages and emails:

SELECT * FROM Message 
   LEFT OUTER JOIN ShortMessage ON ShortMessage.message = Message.id 
   LEFT OUTER JOIN Email ON Email.message = Message.id

This will effectively create a result set very much like what your first option is, with a lot of null fields.

So the basic idea here is that a message potentially has a email. Depending on whether or not you define Email.message to be UNIQUE, you can make sure there’s at most one email corresponding to a message. This setup (like all alternatives you proposed) allows a single message to have multiple different transports, which is actually conceivable in the real world.

Advantages of this approach:

  • (over 1 & 2) Your database is normalized, which usually gives you stuff for free
    • if you want to add new transport types without altering any existing tables (not something you want to do in a huge database)
    • You don’t have to store loads of nulls
  • (over 3) You can query all messages in one query, so you can get all messages to a specific recipient like so:

    SELECT IFNULL(Email.body, ShortMessage.body) as text FROM Message 
      LEFT OUTER JOIN ShortMessage ON ShortMessage.message = Message.id 
      LEFT OUTER JOIN Email ON Email.message = Message.id
      WHERE 
        Email.recepient = "[email protected]" 
        OR ShortMessage.recipient = "01189998819991197253"
    

    And voilà, you’ve got yourself a list of all text ever sent to john doe.

However, if you’re using an ORM, you might actually use the power to perform queries such as that. I am have no practical experience with C#, but from my understanding as an outsider, Linq lends itself well to accessing relational databases for what they are, instead of trying to shoehorn objects semantics onto records (which always makes you hit a very thick wall at some point down the road).

4

Another option is to use a database that natively supports inheritance, e.g. PostgreSQL.

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa

Database design for polymorphic data

I have an application that needs to log communications with users over several different mediums: Email, SMS, Voice, Website Announcements, etc.. in a traditional database.

I have considered 3 approaches to modeling these different types of data:

  1. Single Table Inheritance:
    Store them all together in a single table (i.e., comm_message) with discriminator field of some sort to indicate the type of communications (e.g. message_type). This means that some fields in the table won’t be used for each type–and it means that the same message may be duplicated in several different rows in the table (if the message is sent via more than one medium).

  2. Message “has” transports
    Have a message table (comm_message) and then transports table (comm_transports) with the various different mediums of communication. A many-to-many relationship between messages and transports would mean one row for each message in the message table–but that row might have several different transports. If additional specific information is needed for a particular transport, it could be in it’s own table (i.e. comm_sms, comm_email, etc..) that is linked off the many-to-many table. I.e., a “has-a” approach.

  3. Class Table Inheritance:
    Create a base message table (comm_message) and then another table for each medium with fields specific to it (inheritance). My ORM (LLBLGen) would facilitate this approach by using shared PKs for the different tables. In this approach there would be a row in the base table (comm_message), plus rows in each of the related tables for each transport (comm_email, comm_sms, etc.) but there would be no many-to-many relationship. Rather the records across different tables would share the same PK (1-1). This would be more of an “is-a” approach.

Context: This is a medium sized application (around 100 tables) that I’ll be maintaining for many years–so I’d like to get this “right”. I’ll often need to present all the communications info together in the UI in a grid, reports, etc..

Which should I use? Why?

2

Follow composition over inheritance as composition lends itself well to relational databases.

Say you want to get all short messages:

SELECT * FROM Message INNER JOIN ShortMessage ON ShortMessage.message = Message.id

Say you want to get all short messages and emails:

SELECT * FROM Message 
   LEFT OUTER JOIN ShortMessage ON ShortMessage.message = Message.id 
   LEFT OUTER JOIN Email ON Email.message = Message.id

This will effectively create a result set very much like what your first option is, with a lot of null fields.

So the basic idea here is that a message potentially has a email. Depending on whether or not you define Email.message to be UNIQUE, you can make sure there’s at most one email corresponding to a message. This setup (like all alternatives you proposed) allows a single message to have multiple different transports, which is actually conceivable in the real world.

Advantages of this approach:

  • (over 1 & 2) Your database is normalized, which usually gives you stuff for free
    • if you want to add new transport types without altering any existing tables (not something you want to do in a huge database)
    • You don’t have to store loads of nulls
  • (over 3) You can query all messages in one query, so you can get all messages to a specific recipient like so:

    SELECT IFNULL(Email.body, ShortMessage.body) as text FROM Message 
      LEFT OUTER JOIN ShortMessage ON ShortMessage.message = Message.id 
      LEFT OUTER JOIN Email ON Email.message = Message.id
      WHERE 
        Email.recepient = "[email protected]" 
        OR ShortMessage.recipient = "01189998819991197253"
    

    And voilà, you’ve got yourself a list of all text ever sent to john doe.

However, if you’re using an ORM, you might actually use the power to perform queries such as that. I am have no practical experience with C#, but from my understanding as an outsider, Linq lends itself well to accessing relational databases for what they are, instead of trying to shoehorn objects semantics onto records (which always makes you hit a very thick wall at some point down the road).

4

Another option is to use a database that natively supports inheritance, e.g. PostgreSQL.

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật