Database, store relationships - database-schema

I'm currently making an application to let sportives meet other sportives in order to play together. The problem is about listing relationships in database. I found a working solution as follows.
-------- -----------------
| User | | Relationships |
-------- -----------------
| id | | id |
-------- | idUser1 |
| idUser2 |
-----------------
However I feel like there is room for improvement, is there a better way to solve this situation ?

You don't need id in Relationships, though it could be handy
Add check constraint so that user cannot have relationship with self
Add unique constraint (idUser1, idUser2) so don't duplicate relationships
You are using foreign key yes?
Got indexes?
Consider adding reflexive relationships, ie when add relationship (user1, user2) you would also add (user2, user1) . This might make access control easier and let's someone "defriend" you without you defriending them.
Will there only ever be one type of relationship?

Related

Laravel retrieve field value of a third model from extra field in pivot table

i am working with laravel 9.x.
I have three tables with the three respective models.
one:id | valueA | value2 | value3...
two: id: | valueB
three: id | valueC
The relationships between these models are many to many.
Instead of creating a 3way pivot table I created one for model one and two with the key of three as an extra field
one_id | two_id | three_id
My question is this:
how should i setup relationships between models to access valueC via many to many relationship between one and two?
For now the relationships of the models are
Model One
public function twos(){
return $this->belongsToMany(Two::class)->withPivot('two_id');
}
Model Two
public function ones(){
return $this->belongsToMany(One::class)->withPivot('one_id');
}
Can anyone help me

Entity Framework Core: What relationship to use between two tables with no separate foreign key constraint

I'm currently trying to figure out how to map current database ERD to a C# class relationship using Fluent API. I am familiar with basics of EF Core but can't wrap my head around this problem. This is an example of my ERD:
| tbl_elements |
|---------------|
| element_id |
| last_modified |
| tbl_poles |
|---------------|
| pole_id |
| color |
| height |
| tbl_towers |
|---------------|
| tower_id |
| color |
| type |
I want to map them like this: element_id : pole_id and element_id : tower_id.
However when I use this approach One-To-One I get a foreign key in both tbl_poles and tbl_towers and I don't want this.
I also tried using Inheritance but then I can't use tbl_elements anymore but I need al the tables in my database. I searched the internet for solution and tried al of the provided solutions but didn't found any. I found this: solution, but like I said I need the parent class to be a separate table and not merged.
To give more context: I'm trying to read a shapefile.shp and extract al the features and put them in the corresponding tables.
Until the .NET 5 EF Core has only supported Table-Per-Hierarchy inheritance model. But now it supports also Table-Per-Type and it is pretty easy to configure.
Check the Microsoft Docs.

SQL server with row level security and entity framework

I have a database (MS SQL Server) where row level security is used for the tables. Will there be any complications if I want to use that with Entity Framework. For example assume I have a n:n relation between students and courses like this:
Student:
Bob
Alice
Course:
Math
History
Student_Course:
Bob | Math
Bob | History
Alice | Math
Alice | History
"Course" table has row level access and I am not allowed to see the row "History". So what will happen if I have fetched Bob from the "Student" table and then do something like:
var bobsCourses = bobTheStudent.Courses
The framework is smart enough to give me [Math]?
I get [Math, null]?
Everything will crash and burn because the entry in "Student_Course" does not have a match in "Course"?
The database already exists but not the application so this is "database first"
The application will only be used for data presenting, so no need to care about writing any updates to the database.
It would probably break unless you applied the RLS predicate to the Student_Course table as well. RLS doesn't "cascade" in SQL Server.
I did some testing, it seems to be working like this:
For n:n relations there is no problem, the example works fine and the result will be [Math].
It's a little bit more complicated for 1:1 relations, e.g. assume we have these tables:
Student: ### Table with students + main subject foreign key
Bob | Math
Alice | History
Subject: ### Subjects
Math ### This row is private
History
Then:
AllStudents
will give me [Bob, Alice]
and
BobTheStudent.MainSubject
will simply be null.
But then comes the scary stuff...
AllStudents.Include("MainSubject")
will give me [Alice].
I guess that's because in that case an SQL inner join will be used to retrieve the data from both tables. (Probably it will be different if null values were allowed for the foreign key, but I did not test that.)

Table does not have an inverse; this is an advanced setting (no object can be in multiple destinations for a specific relationship)

I have three tables in my Core Data db. EntityManagedObject, InitiativeManagedObject, ObjectiveManagedObject. There is a 1-2-M relationship between Entity and Initiative; Entity and Objective and Entity and Entity.
I have configured the relationship to be 'to many' but I have not set an inverse relationship because I don't want an inverse relationship. I can't have an inverse relationship anyway for initiatives and objectives the designer doesn't allow it, however it does allow it for entity to entity.
The problem is I am getting these warnings:
EntityManagedObject.entities does not have an inverse; this is an
advanced setting (no object can be in multiple destinations for a
specific relationship)
EntityManagedObject.initiatives does not have an inverse; this is an
advanced setting (no object can be in multiple destinations for a
specific relationship)
EntityManagedObject.objectives does not have an inverse; this is an
advanced setting (no object can be in multiple destinations for a
specific relationship)
I was a bit confused by the inverse relationships at first but it makes sense. I know you are not supposed to think too much in terms of relational databases but in this case I find it helps me.
+--------+ +------------+
| | /| |
| Entity |-----| Initiative |
| | \| |
+--------+ +------------+
Looking at the diagram you would say
An Entity has many Initiatives
An Initiave has one Entity
So those are the two relationships you need to set up.
Entity 'to many' Initiatives
Initiative 'to one' Entity

How do I express a polymorphic association in JPA?

A polymorphic association is similar to a foreign key or many-to-one relationship, with the difference being that the target might be one of a number of types (classes in the language, tables in the db).
I'm porting a database design I've been using for some years from PHP to Java. In the old code, I had rolled my own ORM, which wasn't optimal for a number of reasons. Although I might start to tweak things later, and maybe end up implementing things myself again, for now I'd like to use an off-the-shelf ORM and JPA on my entity classes.
Now, there's one thing about the database layout that I don't know how to express in JPA:
I have a Node and an Edge table storing a graph (a DAG, if it matters). Each node may optionally reference one other entity from the database. These entites may be refrenced multiple times throughout the graph and there may also be "orphaned" entites, which wouldn't be accesible for the user, but which may make sense to keep at least for a while.
These objects are not at all related in terms of inheritance etc. but have a natural hierarchy, similar to Customer->Site->Floor->Room. In fact, years ago, I started out with just foreign key fields pointing to the "parent" objects. However, this hierarchy isn't flexible enough and started falling apart.
For example, I want to allow users to group objects in folders, some objects can have multiple "parents" and also the relations change over time. I need to keep track of how the relations used to be, so the edegs of the graph have a timespan associated with them, that states from when to when that edge was valid.
The link from a node to an object is stored in two columns of the node table, one carries the id in the foreign table, one carries its name. For example (some columns omitted):
table Node:
+--------+-------+----------+
| ixNode | ixRef | sRefType |
+--------+-------+----------+
| 1 | NULL | NULL | <-- this is what a "folder" would look like
| 2 | 17 | Source |
| 3 | 58 | Series | <-- there's seven types of related objects so far
+--------+-------+----------+
table Source (excerpt):
+----------+--------------------+
| ixSource | sName |
+----------+--------------------+
| 16 | 4th floor breaker |
| 17 | 5th floor breaker |
| 18 | 6th floor breaker |
+----------+--------------------+
There might be a different solution than using JPA. I could change something about the table layout or introduce a new table etc. However, I have thought about this a lot already and the table structure seems OK to me. Maybe there's also a third way that I didn't think of.
I think you've already hit on an answer. Create an abstract class (either #Entity or #MappedSuperclass) and have the different types extend it.
Something like this might work
#MappedSuperclass
#Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class Edge {
// . . .
#OneToMany
Collection<Node> nodes;
}
#Entity
public class Source extends Edge {
}
#Entity public class Series extends Edge {
}
#Entity
public class Node {
// . . .
#ManyToOne
Edge edge;
}
I understand you might not want to imply a relationship between the Source and Series, but extending a common abstract (table-less) class is the only way I can think of to do what you want.
InheritanceType.TABLE_PER_CLASS will keep Source and Series in separate tables (you could use SINGLE_TABLE to do something like the previous answer).
If this isn't what you're looking for, many JPA providers provide a tool that creates mappings based on an existing set of tables. In OpenJPA it's called the ReverseMappingTool [1]. The tool will generate Java source files that you can use as a starting point for your mappings. I suspect Hibernate or EclipseLink have something similar, but you could just use the OpenJPA one and use the entity definitions with a different provider (the tool doesn't generate any OpenJPA specific code as far as I know).
[1] http://openjpa.apache.org/builds/latest/docs/manual/manual.html#ref_guide_pc_reverse
The answer would be:
inheritance (as suggested already by Mike)
plus #DiscriminatorColumn to provide information which column stores the information about which subclass should be used: sxRef. The only doubt I see is the "sxRef" being a nullable column. I guess that it's forbidden.
Have you looked at the #Any annotation? It's not part of JPA but is a Hibernate Annotation extension to it.
How much information is stored in the Source and Series tables? Is it just a name? If so, you could combine them into one table, and add a "type" column. Your Node table would lose its sRefType, and you would have a new table that looks like this:
ixSource sName sType
16 4th floor breaker SOURCE
17 5th floor breaker SOURCE
18 6th floor breaker SOURCE
19 1st floor widget SERIES
20 2nd floor widget SERIES
This table would replace the Source and Series tables. Do Source and Series both belong to a superclass? That would be a natural name for this table.