How to implement specific Part/BOM design using two foreign keys from BOM to Part in GORM? - go

Here's a picture of a generic Bill of Materials.
How does one implement the join table named "BOM" above using GORM and its tags? (Ignore the supplier tables.)
type Part struct {
gorm.Model
Parents []Part
Children []Part
}
Update
The goal is to query for a part, P, and be able to show all the parts that P is used in and all the parts P uses. The ER diagram designs this kind of solution in the database. I've built solutions in SQL and other languages to do this. Now I'd like to use GORM to provide it.
Because Quantity is in the join table, there will have to be a declared struct rather than a GORM generated join table. Something like this:
type Bom struct {
Parent Part
Child Part
Quantity int
}
How do I indicate to GORM that Bom has two foreign keys into Part?
How do I furnish the slices in Part from Bom?

Related

define associative model in Golang gorm

I am using golang gorm in my RestFul service, however, now I have a doubt that might be simple but I cannot find any example or specific documentation, its not clear to me.
Let's say that I have the tables users and languages, any user can have many languages and any language can have many users, in this case for theory of relational database modeling we have to create a table users_languages, and checking gorm I see that I will have to use many to many relationship.
By now, I have the structs that define the user and language tables, lets say:
type User struct {
gorm.Model
Languages []Language `gorm:"many2many:user_languages;"`
}
type Language struct {
gorm.Model
Name string
}
Then I ran the migrations and the tables User and Language were created. My question is, how should I define then the structure of the user_languages table? how the foreign keys are set there?
how should I define then the structure of the user_languages table?
You should also describe the user_languages model for many2many relations like User and Language as example
type UserLanguages struct {
gorm.Model
UserId int
LanguageId int
}
And probably you should define primary keys for User and Language models
how the foreign keys are set there?
GORM generates names of foreign keys in queries yourself, in underscore format (like user_id, language_id), for redefining it you can use special AssociationForeignKey annotation on model fields, I hope it will help!

Golang Gorm: Is it possible to delete a record via a many2many relationship?

I have a many2many structure similar to GORM's example:
// User has and belongs to many languages, use `user_languages` as join table
type User struct {
gorm.Model
Languages []Language `gorm:"many2many:user_languages;"`
}
type Language struct {
gorm.Model
Name string
}
db.Model(&user).Related(&languages)
Let's say I create a user and it has two associated languages.
I fetch a user record from the database and remove one language from the user's Languages array. I then save the user with gorm:save_associations set to true.
I would expect GORM to delete the record associating the user to this language (in the association table that GORM manages). However, it is not deleted. Is this expected?
Is it possible to delete many2many association records by removing a language from the Languages list on the user record and then saving the user? If not, how should this be done in GORM?
Update
I found a solution to this question, but not sure it's the best way to do this. I store the current languages, clear all the associations, then add back the languages, then save.
languages := user.Languages
DB.Model(&user).Association("Languages").Clear()
user.Languages = languages
I was having the same problem, If you want to just remove one of the associations this worked for me
c.DB.Model(&user).Association("Roles").Delete(&role)
Also, you can do this by using "replace"
DB.Model(&user).Association("Languages").Replace(user.Languages)
I found a solution to this question, but not sure it's the best way to do this. I store the current languages, clear all the associations, then add back the languages, then save.
languages := user.Languages
DB.Model(&user).Association("Languages").Clear()
user.Languages = languages
This is something that i am using it. If this is helpful to anyone.
db.Preload("Languages").Find(&user, r.FormValues("id"))
db.Model(&user).Association("Languages").Clear()
db.Save(&user) // We are deleting all the records first
.....
.....
user.Languages = languages
db.Save(&user) // Re insert all the records

EAV - Get value using Linq to entities

In a data model like this (http://alanstorm.com/2009/img/magento-book/eav.png) I want to get the value from an EAV_Attribute using Linq to SQL.
Assuming that an EAV_Attribute only exists in one inherited table (varchar, decimal, int, etc.) how can I get it in a linq query?
I know that I can use the Inheritance for this, but I want to execute it in the SQL Database side...
Is it possible to do a kind of Coalesce in Linq, considering that the elements have different types?
EAV and linq is not a happy marriage. I think your best shot is to create an unmapped property in eav_attribute that resolves the value (as object) from it's typed attribute child. With entity framework, you won't be able to use this property in an expression (i.e. not in a Where or Select), You must convert to IEnumerable first to access it. (Linq-to-sql may allow it because it can switch to linq-to-objects below the hood).
Another option is to create a calculated column of type sql_variant that does the same, but now in t-sql code. But... EF does not suport sql_variant. You've got to use some trickery to read it.
That's the reading part.
For setting/modifying/deleting values I don't see any shortcuts. You just have to handle the objects as any object graph with parents and children. In sql server you can't use cascaded delete because it can only be defined for one foreign key. (This may tackle that, but I never tried).
So, not really good news, I'm afraid. Maybe good to know that in one project I also work with a database that has an inevitable EAV part. We do it with EF too, but it's not without friction.
First of all, I recommend using TPH and not TPT for EAV tables. (One table with multiple nullable value columns (one per type) + discriminator vs. one table per type.)
Either way, if you modelled the value entity as an abstract class (containing the two IDs) with an inheriting entity per value data type that adds the value property, then your LINQ should look like this:
var valueEntity = context.ProductAttributes.Where(pa =>
pa.ProductId == selectedProductId
&& pa.AttributeTypeId == selectedAttributeTypeId)
.SingleOrDefault() as ProductAttributeOfDouble;
if valueEntity != null
return valueEntity.Value;
return null;
Where the entity types are: Product, AttributeType, ProductAttribute, ProductAttributeOfDouble, ... ProductAttributeOfString.

What are relations on Extended Data Types used for?

I can see that Extended Data Types can have Array Element which seems to make it a composite type. I'll be looking into that later.
What are the relations used for? MSDN was woefully crap at explainined what it would actually be used for. Why would you want to relate a type to a specific table and why would other tables using the type care?
When I create a new 'PersonTable' table I could have a key field called personId, creating/using a new Extended Data Types called personId and adding the relation you've mentioned. Now when I add our EDT to other tables we do not have to specify either labels or relations to our PersonTable as this it's defined by the extended data type.
In a related form (e.g. PersonSkillsTable) where our personid field has been added to an existing table it will now automatically create the dropdown/grid to select a value from our persontable. We didn't need to add our persontable to the form's Data Source.
Automatic relations between tables
Automatic lookups
Automatic "Go To Main Table" menu option after right-click

how can I 'walk' the relationships between tables in LINQ?

Let's say I have three tables:
Office
ID
SalespeopleOffice
ID
OfficeID
PersonID
People
ID
ManagerID
In LINQ to SQL, how can I start from the SalespeopleOffices table and "walk" from that table to the People table or the Office table via the relationships between the tables? Specifically without knowing what those relationships are; pull the data about the relationships instead of interacting with the objects directly. I'm looking for a way to programatically analyze table relationships. The database I'm working with has many more tables than this, so in reality it's a lot more complex than this.
I'd ideally like to create a LinqPad script to do this.
You can use reflection to examine the properties on each type in the context. (In LinqPad, the context is this).
Value and string properties will be scalar fields on the table,
EntitySet properties will represent [something]-to-many relationships, and
other types will be [something]-to-one relationships.
If you connect the two sides of the relationships you can figure out what the [something] is in each case. Does that make sense?
Edit
I was just poking around a little, and there's a better approach. The model information is available via the Mapping property. Try this:
var tableData = from t in this.Mapping.GetTables()
select new
{
t.TableName,
Associations =
from a in t.RowType.Associations
select new
{
a.ThisMember.Name,
TypeName = a.ThisMember.Type.Name
}
};
tableData.Dump();
Assuming you've activated Auto Completion, it should be a piece of cake to find the exact data you're interested in by exploring the properties on this meta data.
If you're using LINQ to SQL, your SalespeopleOffices instances shoud have People and Office properties.
Something like:
var salesPO = dataContext.SalespeopleOffices.First()
var office = salesPO.Office
var man = salesPO.People

Resources