Defining Laravel Eloquent Relationship Through Many to Many Relationship Table - eloquent

table deal_order have field deal_id and order_id. orders table belong to customer table. how do i define laravel Eloquent relationship between deals table and customer table in Deal Model class
deals
id
product_id
order
id
customer_id
deal_order
deal_id
order_id
customers
id
name
class Deal extends Model {
public function customer() {
return $this->hasManyThrough(Customer::class, Order::class, 'order_id', 'id', 'deal_id', 'customer_id');
}
}
class Order extends Model {
public function deals() {
return $this->belongsToMany(Deal::class, 'deal_order', 'order_id', 'deal_id');
}
public function customer() {
return $this->belongsTo(Customer::class);
}
}
class Customer extends Model {
public function orders() {
return $this->hasMany(Order::class);
}
}

Related

EF Core 'no such table' when using base class

For starters, I have an entity structure that I cannot change.
My Database has a Person table and a Users table (for the context of this question).
CREATE TABLE [Person] ...
CREATE TABLE [User] ...
My entities are using some inheritance
public abstract PersonBase
{
public string Id { get; set; }
// person meta data
}
public class Person : PersonBase
{
// additional data for app 1
}
public class User
{
public string PersonId { get; set; }
public PersonBase Person { get; set; } // I cannot change this #sadpanda
}
When I try and configure the relationship
public class UserConfiguration : IEntityTypeConfiguration<User>
{
public void Configure(EntityTypeBuilder<User> builder)
{
builder.HasOne(x => x.Person).WithMany().HasForeignKey(x => x.PersonId);
}
}
And subsequently try to query it, EF Core generates the following query
SELECT ...
FROM "User" AS "e"
LEFT JOIN (
SELECT "e0".*
FROM "PersonBase" AS "e0"
WHERE "e0"."Deleted" = 0
) AS "t" ON "e"."PersonId" = "t"."Id"
....
And I get an error
SQLite Error 1: 'no such table: PersonBase'.
Is there any way to get this configured so that when I try to hydrate the User.Person, EF will use the Person table from the database even though the entity type is PersonBase?
note: to re-iterate, I cannot change the Entity structure, but I have full control over my Entity Configuration.
I tried setting up my configuration with strings
builder.HasOne("Person").WithMany().HasForeignKey("PersonId");
But then it complained about shadow state
Entity type 'Person' is in shadow-state. A valid model requires all entity types to have corresponding CLR type.

laravel hasone get name from id

I have a table with:
id
employee_name
manager_id
In this table, manager id is a foreign key to id in same table.
I have another table with projects
id
employee_id
In this table, employee_id is a foreign key to id in the employee table
I try to get the name from the manager_id like this in the controller:
public function show(Employee $managers, $id)
{
$manager = $managers::find($id)->manager;
\Debugbar::info($manager);
}
And my App\Employee file is like this:
class Employee extends Model {
protected $table = 'employees';
public $timestamps = true;
public function projects()
{
return $this->hasMany('App\Projects');
}
public function manager()
{
return $this->hasOne('App\Employee');
}
}
The proble is I get:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'employees.employee_id' in 'where clause' (SQL: select * from `employees` where `employees`.`employee_id` = 1 and `employees`.`employee_id` is not null limit 1)
To me it shows that it is taking employee_id in the sal statement from the other function where it should only take id as it is in the same table.
You should change:
public function manager()
{
return $this->hasOne('App\Employee');
}
into
public function manager()
{
return $this->belongsTo('App\Employee','manager_id');
}
You can do it without the manager_id I expect the 2nd parameter is for when you have an id that does not follow the tablename_id convention.
public function manager()
{
return $this->belongsTo('App\Employee');
}

Laravel 5 Eloquent Relationship - Has Many Though

I have three models.
Study
Site
Unit
Study Has and belongs to many Sites and each site that belongs to Study again has and belongs to many Unit. Please see the following drawing.
http://tinypic.com/r/ojhx0g/8
How I achieve this using Laravel 5 Eloquent Relationships.
It sounds like you have many-to-many relationships between Study->Site and Site->Unit. You can read the Laravel documentation about many-to-many relationships here.
Models
Here are the relevant functions you'll need for Eloquent to recognize the relationships.
class Study extends Model {
// If you named your table differently (like 'studies'), specify that here
protected $table = 'studys';
// This assumes a pivot table named 'site_study', if you named yours
// differently you can pass in into the belongsToMany() function as the
// second parameter.
public function sites() {
return $this->belongsToMany('App\Site');
}
}
class Site extends Model {
protected $table = 'sites';
public function studies() {
return $this->belongsToMany('App\Study');
}
public function units() {
return $this->belongsToMany('App\Unit');
}
}
class Unit extends Model {
protected $table = 'units';
public function sites() {
return $this->belongsToMany('App\Site');
}
}
Then, to access the Sites belonging to a Study you would do this:
$sites = Study::find(1)->sites;
Pivot Table Migrations
Laravel expects pivot tables to be named like 'alpha_beta' where alpha and beta are the singular model names in alphabetical order. So your migrations for the pivot tables would look like this:
class CreateSiteStudyTable extends Migration {
public function up() {
Schema::create('site_study', function(Blueprint $table)) {
$table->integer('site_id')->unsigned();
$table->foreign('site_id')->references('id')->on('sites');
$table->integer('study_id')->unsigned();
$table->foreign('study_id')->references('id')->on('studys'); // or whatever you named it
$table->unique(['site_id', 'study_id']);
$table->timestamps();
});
}
public function down() {
Schema::drop('site_study');
}
}
class CreateSiteUnitTable extends Migration {
public function up() {
Schema::create('site_unit', function(Blueprint $table)) {
$table->integer('site_id')->unsigned();
$table->foreign('site_id')->references('id')->on('sites');
$table->integer('unit_id')->unsigned();
$table->foreign('unit_id')->references('id')->on('units');
$table->unique(['site_id', 'unit_id']);
$table->timestamps();
});
}
public function down() {
Schema::drop('site_unit');
}
}
You can read about Foreign Keys in Laravel here.
you have to create 3 models study, site and unit as per you diagram study has many sites and sites has many units, in you diagram study don't have direct relation with units your eloquent models will be like this.
class Study extends Model {
public function sites(){
return $this->hasMany('App\Site');
}
}
class Site extends Model {
public function units(){
return $this->hasMany('App\Unit');
}
public function study(){
return $this->belongsTo('App\Study');
}
}
class Unit extends Model {
public function sites(){
return $this->belongsTo('App\Site');
}
}

TPH Discriminator not on base class / table

I'm having an issue with discriminators in TPH inheritance with Entity Framework v6.1.1
I would expect that the discriminator should fall on the table that is representative of the base class. However, it appears EF is trying to map the discriminator column to the table mapped to the derived class
E.g.
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Staff : Person
{
public decimal? Salary { get; set; }
}
public class MyContext : DbContext
{
public MyContext()
: base("MyConnectionString") {}
public virtual IDbSet<Person> Persons { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Person>()
.Map(x => x.ToTable("Person"))
.Map<Staff>(x => x.ToTable("Staff").Requires("PersonTypeId").HasValue(1));
}
}
I am also using an existing schema too - i.e:
CREATE TABLE Person
(
Id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
Name VARCHAR(50) NULL,
PersonTypeId INT NOT NULL
)
CREATE TABLE Staff
(
Id INT NOT NULL REFERENCES Person(Id),
Salary DECIMAL NULL
)
GO
However, when I try to add a new Staff, I encounter the following exception:
'System.Data.SqlClient.SqlException : Cannot insert the value NULL into column 'PersonTypeId', table 'MyDb.dbo.Person'; column does not allow nulls. INSERT fails.
The statement has been terminated'
It appears that it is trying to insert the discriminator (incorrectly) to the derived table. Hope someone can help.
So it appears that I've mis-understood the TPH setup for Entity Framework.
In my case, I'm wanting to map derived types to separate tables, which is an example of Table per Type - http://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-2-table-per-type-tpt
Discriminators are redundant in this context.

Code First: TPT inheritance - Specify a different name for the primary key column in each table

I've posted my problem on codeplex http://entityframework.codeplex.com/workitem/2087.
There are also some questions posted here but they are not successfully answered.
See
Mapping TPT in EF Code First 4.1 w/ Different Primary Keys
Entity Framework 4 - TPT Inheritance in Features CTP5 (code first): rename foreign key column on inherited table
How can I use TPT inheritance models when primary keys have different names?
Is it now possible to have different column names for the primary keys when using TPT?
May be with 6.1.0
In TPT you're essentially do not want to declare the key in the subclasses, you'd miss the point otherwise.
If you must have a different Id name, just make proxy properties in the subclasses mapping to the base Id one.
public class BaseEntity
{
public int Id { get; set; }
}
public abstract class SubEntity : BaseEntity
{
public BaseId
{
get => Id;
set => Id = value;
}
}
Consider marking the sub fields as NotMapped, which in case you shouldn't include them in your LINQ queries.
With EF 6.4 I was able to use the ColumnAttribute to rename the Primary Key column in the dependent class
[Table("Person")]
public class Person
{
[Key]
public virtual int PersonId { get; set; }
// Person atributes...
}
[Table("Employee")]
public class Employee : Person
{
[Column("EmployeeId")] // <- Name of the primary Key column in the Database
public override int PersonId { get; set }
// Employee Attributes
}
Look at this code snip. Its work correct for me:
public partial class Person
{
// Any other PK name can thrown an exception
public int ID { get; set; }
}
public partial class Employee : Person
{
// Hide base class ID
private new int ID { get; set }
// Define derived class ID (that wrapped inherited ID)
[NotMapped]
public int EmployeeID
{
get { return base.PersonID; }
set { base.PersonID = value; }
}
}
Now, we must rename the inherited ID (with fluent API) for database table:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Employee>()
.Property(e => e.ID)
.HasColumnName("EmployeeID");
}