Mapping multiple tables into a single Entity in Entity Framework - asp.net-mvc-3

In in a website's database I am working on, I have two tables for example: Country & CountryLocale. The two tables contain the following columns:
Country: Id, Longitude, Latitude
CountryLocale: Id, CountryId, CountryName, CultureId
What I want is:
- When I retrieve a Country, I want the Entity to contain: CountryId, CountryName, CultureId, Latitude & Longitude.
- When I create a new Country, to insert one record into Table Country and one to Table CountryLocale.
- When I create a new Country Locale, to create a record inside CountryLocale only
etc ...
Is this attainable?
Thanks

You can use entity splitting to partially achieve that. CountryLocale would use the PK of Country as its PK. You can not insert to CountryLocale without a Country. Essentially its a single entity split into multiple tables.
modelBuilder.Entity<Country>()
.Map(mc =>
{
mc.Properties(n => new
{
n.Id,
n.Longitude,
n.Latitude
});
mc.ToTable("Country");
})
.Map(mc =>
{
mc.Properties(n => new
{
n.CountryName,
n.CultureId
});
mc.ToTable("CountryLocale");
});

use discriminator (Table per Hierarchy)
modelBuilder.Entity<CountryBase>()
.Map<Country>(c => c.Requires("Type").HasValue((int)CountryType.Country))
.Map<CountryLocale>(c => c.Requires("Type").HasValue((int)CountryType.CountryLocale));
and you can define your sub-entities as you like

Related

How to access multiple model data from an eloquent call

I currently have a product table with the following columns:
id, product_name, product_type, description
I also have three more tables:
medias, attributes, coatings
each of those tables has an id, name, description, img
Each product created din the product table will have multiple, medias, attributes and coatings. To address this I created a table product_relations which contains the columns:
id, product_id, media_id, attribute_id, coating_id
From here I thought I would make a call to product_relations with the product_id and then pull each record so I can access the data. However I'm stuck on how I would do this as an eloquent relationship. Would I do separate has many's in my Product_Relation model like so:
public function media()
{
return $this->hasMany('App\Media');
}
public function attributes()
{
return $this->hasMany('App\Attributes');
}
etc? Or is there a simpler way to build this to access all that at once?

Hasura: How to establish relationship to existing record (many to many) at insert time?

Hasura: How to establish relationship to existing record (many to many) at insert time?
I have two tables: product and category that are linked to each other in a many to many relationship based on an id column in each table and an intermediary table product_category.
I can insert records directly into postgres for both tables and link them with product_category and this works great in Hasura for queries so I know I have set things up properly.
What I want to be able to do is insert a new product and knowing the id of a category (or categories) I want to establish the relationship at insert time. Preferably without a seperate call
https://hasura.io/docs/1.0/graphql/manual/mutations/insert.html#insert-an-object-along-with-its-related-objects-through-relationships
The documentation only covers inserting both the object and related objects at the same time but what if the other one already exists?
I have tried what I would expect to work (linking this product to category with id 1):
mutation MyMutation {
insert_product_one(
object: {
name: "Champion",
category: {data: {id: 1}}
}) {
id
}
}
But that throws:
"Not-NULL violation. null value in column \"product_id\" violates not-null constraint"
How can I insert this new product and link it to one or more categories? Preferably all in one statement but even an example of retrieving the generated id and an update mutation would be not ideal, but non-the-less a solution.
Update: As a sanity check I've recreated the product and category tables as a minimal, basic example and tried both my query and the upsert conflict method xadm suggested.
The data and relations I've added some screenshots of here:
https://imgur.com/a/GUomMbe
mutation MyMutation {
insert_testproduct_one(
object: {
name: "Champion",
category: {
data: {id: 1},
on_conflict: { constraint: primarykeything , update_columns: [id] }
}
}) {
id
}
}
The error is similar: "Not-NULL violation. null value in column \"testcategory_id\" violates not-null constraint"
Note: primarykeything is the primary key on the bridge table consisting of the two ids.
Since it's a many to many relationship, you have a join table in between them. From what I can see in the screenshot you posted the id for the category in your category relationship is called testcategory_id and not id.
mutation MyMutation {
insert_testproduct_one(
object: {
name: "Champion",
category: {
data: {testcategory_id: 1}
}
}) {
id
}
}
For it to work the id in the table testproduct_testcategory has to be auto-incremented

Entity Framework & Linq Orderby

We have a 3 table relationship in an MVC application that is using the EF6. For example a Customer Table related to an Orders Table(the many side) and the Orders Table is related to an OrderItems Table (the many side).
We would like in ONE TRIP to the database get all the records for all tables and be able to order each table.
We know we can use the include extension like context.Customers.Include("Orders.OrderItems") to eagerly load all data. But we keep getting errors when we try to order each table.
For example we would like to order the Customer Table by CustomerId column, and the Orders Table by Date column and the OrderItems by ProductId column.
Any assistance would be apreciated
If you have navigation properties from OrderItem to Order and from Order to Customer, then you can get ordered `OrderItems' you can achieve this like:
var orderItems = context.OrderItems
// Filter if needed with .When
.Include(m => m.Order.Customer)
.OrderBy(m => m.Order.Customer.CustomerId)
.ThenBy(m => m.Order.Date)
.ThenBy(m => m.ProducetId)
.ToList();
But, if you want to get customers, what you can do is load ordered customers like:
var customers = context.Custoemr
.Include(m => m.Orders.Select(o => o.OrderItem))
.OrderBy(m => m.CustomerId)
.ToList();
Then order Order and OrderItem. As you have loaded all data, ordering collections will not make any database call, and it will remain one-trip to database:
foreach(Customer customer in customers)
{
customer.Orders = customer.Orders.OrderBy(m => m.Date);
foreach (Order order in customer.Orders)
{
order.OrderItems = order.OrderItems.OrderBy(m => m.ProducetId);
}
}

Querying with Eloquent - Achieve Join

How to select records from db from a situation like below using eloquent
Tables:
Employee Table [ id,name]
Address Table [id,address_line1,employee_id,city_id]
City Table [id,name]
A Query like below does only return city id, but i need the city name as well
$employee = Employee::with('address')->get();
And My Employee Model have relationship as
public function address(){
$this->hasMany('address');
}
How to achieve the desired result so that the output of the query should give me city name from city table, based on the id from address table, without running new query for each city id to get names

A BaseClass extends from Eloquent to handle complicated search condition in laravel

Previous description of my problem is wrong. So I delete it and write a new one.
There are several tables, following are their structures
Table1: id, name
Table2: id, name, date1, date2
Table3: id, name, desc
maybe more tables...
And some html pages, each one references to a table. Every page has one or more search box to search data in related table. I use Ajax to handle the search work. I take some examples as below
Page related table search columns http params
Page1: Table1 id, name q={"id": 1, "name":"bill"}
Page2: Table2 id, date1, date2 q={"id": 1, "date1":"2014-7-19", "date2":"2014-7-20"}
Page3: Table3 id, name q={"id": 1, "name":"bill", "desc":"boss"}
Then I want to create a BaseModel extends from Eloquent, then all other specific Models extends from BaseModel.
I hope there will be a "search" method it can handle all of complicated search actions in BaseModel.
It's hard to suggest a good solution since you don't really tell us, what needs to be done.
This is the most straightforward solution for you, using query scopes:
// BaseModel extending Eloquent Model
public function scopeSearch($query, $jsonSearch)
{
$wheres = $this->parseSearch($jsonSearch);
$query->where($wheres); // WHERE X = Y AND Z = A ...
}
protected function parseSearch($jsonSearch)
{
// validate your input here, make sure it's correct according to your needs
}
Then:
// single result
AnyModel::search($yourJson)->first();
// collection
AnyModel::search($yourJson)->get();
// you can chain more methods if you like
AnyModel::search($yourJson)->where('x', 'y')->orderBy('x')->get();

Resources