From reading the docs in Grails I found the following statement:
However, excessive use of inheritance and table-per-subclass can
result in poor query performance due to the use of outer join queries.
In general our advice is if you're going to use inheritance, don't
abuse it and don't make your inheritance hierarchy too deep.
My question is: how deep is too deep?
Will 5 extensions in an inheritance chain make Grails cry?, 10?, 20?... what is the criteria to determine this?, or do we know if there is a clear way to extrapolate such performance degradation?
How deep is too deep? is a rather subjective question. But, it's possible to make an educated guess when you consider what happens at the database level with table-per-subclass inheritance. Lets assume you have these domain classes:
class Employee {
String firstName
String lastName
static constraints = {
}
static mapping = {
tablePerHierarchy false
}
}
class Supervisor extends Employee {
String office
static constraints = {
}
}
You'd end up with two tables: EMPLOYEE and SUPERVISOR. The EMPLOYEE table would contain the columns id, first_name, and last_name. But notice that the SUPERVISOR table would only contain the columns id and office.
This means that to retrieve a Supervisor GORM has to join both tables in order to populate the inherited properties.
SELECT EMPLOYEE.ID, FIRST_NAME, LAST_NAME, OFFICE
FROM SUPERVISOR INNER JOIN EMPLOYEE
ON SUPERVISOR.ID = EMPLOYEE.ID
It's these joins which have the potential to result in reduced performance. As you can imagine, 10 or 20 levels of inheritance would be disastrous. Yet a few, especially if the tables are small, would likely be OK.
Besides, a deep inheritance hierarchy is a sign that something is probably wrong with the domain model architecture (ie. consider using Traits).
You can read more about both forms of inheritance in my article here.
Related
As the title states, I need to tell grails GORM that a domain class has a many to many relationship to itself.
In my system, I have a class "course", this "course" class can have none, one or many correlatives.
Taking the example:
mathematical analysis 2
To be able to take the mathematical analysis 2 course, you need to have approved mathematical analysis 1 and physics courses.
mathematical analysis 1 does not have any correlatives or courses to be approved to be able to anyone to take the course.
I have the following:
class Course {
String name
static hasMany = [correlatives: Course]
static belongsTo = [target_course: Course]
}
But it does not seem to have the impact in the Data base that I expect.
Im expecting to have a course_course table that has the many to many to itself like the following:
course_course
int id_course_course
int id_correlative_course
int id_target_course
Am I missing something important here?, help please!
You don't need a many to many table to represent that. While each Course may "have many" correlatives, each correlated course only has one parent.
This is sufficiently represented by a single table like (heavily depending on any mappings you specify):
course:
id (int)
name (varchar)
target_course_id (int, nullable)
I will preface it by saying I'm a database person, moving into .NET, MVC, EF etc. So I fully understand about joins and foreign keys and so on but I am struggling with the EF side.
I worked through a tutorial where we did the following:
create a Student table (StudentID and personal details), a Course table (CourseID and subject details), and an Enrollment table (EnrollmentID, student and course IDs and the grade given to that student for that class).
create Models, Controllers and Views for Student and Enrollment entities to allow editing the name of a Student, enrolling a student for a class and giving them a grade, list out all enrollments, etc.
In that tutorial the Enrollments table is (what I know as) a "bridge" table because student to class is a many-to-many relationship.
So do I only need this "intermediate" model/view/controller if it's a many-to-many scenario like this?
The actual structure I want to program is:
Article (ArticleID, title, author, summary, content...) is a member of a
Category (CategoryID, title, description, ...)
Then I want to have a drop down list (or whatever UI element) of Categories of which clicking on the selected Category will give a page with a table of Title/Author/Summary of the articles that go in that category.
If an Article can be in more than one category ("Effective Use of Catnip" could be under both "Playing Games with Cats" and "Life Hacks") is that where I would need a 'bridge' table?
Please can someone explain in simple terms - whether I am just being put off by the "many to many" nature of the data in that tutorial, or if the 'bridge' table structure is more fundamental to EF for navigating a PK/FK relationship.
I think the tutorial you are reading is trying to introduce you to the basic concepts of EF. If you have a many-to-many relationship, on database side you will always have three tables:
Student
Course
Enrollment (Student_Id, Course_Id)
On EF world, you can represent those three tables as three different entities. However, if you want to have a more "natural" way of representing the relation between Students and Courses, EF allows you to declare many-to-many as two lists:
public class Student {
... properties
virtual List<Course> Courses;
}
public class Course {
... properties
virtual List<Student> Students;
}
However, you need to instruct EF how this references on both side needs to be treated. For that, you can use fluent API. With this fluent API you can define the table name that references both tables/entities:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Student>()
.HasMany<Course>(s => s.Courses)
.WithMany(c => c.Students)
.Map(cs =>
{
cs.MapLeftKey("StudentRefId");
cs.MapRightKey("CourseRefId");
cs.ToTable("StudentCourse");
});
}
Check this article explaining the M:N relationship using fluent library API. Is really simple, and with that you don't need this additional element on the middle.
In terms of UI, you just need to select the list of courses the student want to take, or the list of students the course has to have. Is up to you how you want to present the information to the user, as both functionalities (students taking courses and courses defining its students) point to the same m:n relation.
I think a simple way can be to show a </select> list with the students, and then show the list of courses he can apply to.
The project you want to create uses the same ideas. Basically, with EF you will always need to think in terms of "tables". It is true that EF allows you to abstract your tables to entities, but still you need to follow some rules. To sum up: you are right. The "bridge" table is where you need to store the many-to-many relationships.
Using EF6 Code-First in a party-planning app, I'm trying to model a Party entity with an Attendees property (e.g. ICollection<???> Attendees) where attendees can either be a Person or a Family and where a Family contains a collection of Person instances.
I've read through the helpful series of Code-First modeling articles here: http://weblogs.asp.net/manavi/associations-in-ef-4-1-code-first-part-1-introduction-and-basic-concepts. If attendees were Dog or Cat or some other mutually-exclusive, unrelated types then the advice in those articles is clear.
But what's the right way to model a collection of entities that may be related to each other like Person and Family are?
EDIT: The main problem I'm trying to solve here is how to model the ICollection<???> Attendees property of the Party entity. Specifically, the articles linked above give advice (quoted below) about choosing a modeling strategy for inheritance. In my use-case, one derived type (Family) contains instances from another derived type (Person). Does this suggest that I should use one of the strategies over the other? Or is this fact not very relevant to choice of modeling strategy?
There are three different approaches to representing an inheritance
hierarchy:
Table per Hierarchy (TPH): Enable polymorphism by denormalizing the SQL schema, and utilize a type discriminator column that holds type
information.
Table per Type (TPT): Represent "is a" (inheritance) relationships as "has a" (foreign key) relationships.
Table per Concrete class (TPC): Discard polymorphism and inheritance relationships completely from the SQL schema.
<snip>
Before we get into this discussion, I want to emphasize that there is
no one single "best strategy fits all scenarios" exists. As you saw,
each of the approaches have their own advantages and drawbacks. Here
are some rules of thumb to identify the best strategy in a particular
scenario:
If you don’t require polymorphic associations or queries, lean toward TPC—in other words, if you never or rarely query for
BillingDetails and you have no class that has an association to
BillingDetail base class. I recommend TPC (only) for the top level of
your class hierarchy, where polymorphism isn’t usually required, and
when modification of the base class in the future is unlikely.
If you do require polymorphic associations or queries, and subclasses declare relatively few properties (particularly if the main
difference between subclasses is in their behavior), lean toward TPH.
Your goal is to minimize the number of nullable columns and to
convince yourself (and your DBA) that a denormalized schema won’t
create problems in the long run.
If you do require polymorphic associations or queries, and subclasses declare many properties (subclasses differ mainly by the
data they hold), lean toward TPT. Or, depending on the width and depth
of your inheritance hierarchy and the possible cost of joins versus
unions, use TPC.
By default, choose TPH only for simple problems. For more complex
cases (or when you’re overruled by a data modeler insisting on the
importance of nullability constraints and normalization), you should
consider the TPT strategy. But at that point, ask yourself whether it
may not be better to remodel inheritance as delegation in the object
model (delegation is a way of making composition as powerful for reuse
as inheritance). Complex inheritance is often best avoided for all
sorts of reasons unrelated to persistence or ORM. EF acts as a buffer
between the domain and relational models, but that doesn’t mean you
can ignore persistence concerns when designing your classes.
your model look like this :
public class Family
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Person> People { get; set; }
}
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Family Family { get; set; }
}
and add some config like this:
HasRequired(row => row.Family).WithMany().HasForeignKey(row => row.FamilyId).WillCascadeOnDelete(false);
I've two domain classes which are bonded with a bidirectional one-to-one relationship to each other, this being implemented using hasOne.
class AssessmentData {
static hasOne = [assessmentField:AssessmentField, assessment:Assessment]
AssessmentField field
}
class Assessment {
AssessmentData assessmentData
}
But I'm quite a bit confused about the way Grails implements this relationship at the database level. As described here, it simply sets the foreign key at the child domain class only, in my case, to the Assessment and AssessmentField tables. Its my primitive instinct that both tables should have a foreign key referring to each other in order to establish a one-to-one bidirectional relationship. But since this is not the case, I wanna know how this is achieved by Grails.
Its my primitive instinct that both tables should have a foreign key referring to each other in order to establish a one-to-one bidirectional relationship
Your instincts have failed you. The domain described in your question will generate these 2 database tables:
assessment_data
----------------
id
assessment
----------------
id
assessment_data_id
Using SQL we can get the assessment associated with an assessment_data with id 4
select * from assessment where assessment_data_id = 4
We can also go the other way and get the assessment_data associated with an assessment with id 5 using
select ad.* from assessment_data ad
inner join assessment a ON a.assessment_data_id = ad.id
where a.id = 5
So if we can "go both ways" in SQL, then we can do it with HQL, criteria queries, dynamic finders, etc. because these all ultimately get translated to SQL.
I want to create a hierarchical object model in ASP.NET MVC, but I'm not sure what would be the best way to design database for this. I have a Product base class with certain properties like Title, Price, OnHandQty etc. I have several inherited classes like Book, which has extra properties like ISBN number, Author etc. Many of my products will fall under generic (base) Product class, but some products will fall under these derived classes (e.g. Book). I am not sure what is the best methodology to map this to database. Should I create separate tables for each product type (including one for generic product)? Or is there any better way?
Please note that I'm not really asking about OR mapping. I know how to create classes from DB tables using Entity Framework. But in this case I am confused about the database design itself.
If you are going to use Entity Framework then you should check out Inheritance with EF Code First by mortezam. He explains three strategies that can be used for representing an inheritance hierarchy:
Table per Hierarchy (TPH): Enable
polymorphism by denormalizing the
SQL schema, and utilize a type
discriminator column that holds type
information.
Table per Type (TPT): Represent "is
a" (inheritance) relationships as
"has a" (foreign key) relationships.
Table per Concrete class (TPC):
Discard polymorphism and inheritance
relationships completely from the
SQL schema.
The idea (with Code First) is that you define your classes and inheritance and let the framework create the database for you. That way you don't need to worry so much about the database design.
You might also want to think about using an Object Database or one of the NoSQL storage strategies like Mongo DB which work better than relational databases when you have these kind of 'jagged' classes.