laravel hasone get name from id - eloquent

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');
}

Related

Defining Laravel Eloquent Relationship Through Many to Many Relationship Table

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);
}
}

Insert to sql server by entity error utf-8

I'm try insert this row to my table
student (
id (int)
,name (nvarchar)
)
But when I insert this value (1,"bơ") to student result in my database is
(1,"bo?")
this is my code
public bool Insert() {
Admin_KX_MainDbEntities db = new Admin_KX_MainDbEntities();
student student = new student() {
id = 1,
name = "bơ"
};
db.students.add(student);
db.SaveChanges();
}

Updating a many-to-many relation with Entity Framework

I'm struggling a bit with a many-to-many relation update using Entity Framework. My tables looks like this:
CREATE TABLE Agreement
(
ID int NOT NULL IDENTITY(1,1),
CONSTRAINT [PK_Agreement] PRIMARY KEY CLUSTERED (ID),
);
CREATE TABLE Price
(
ID int NOT NULL IDENTITY(1,1),
ProductPrice decimal(18,5),
CONSTRAINT [PK_Price] PRIMARY KEY CLUSTERED (ID),
);
CREATE TABLE AgreementPriceLine
(
AgreementID int NOT NULL,
PriceID int NOT NULL,
CONSTRAINT [PK_AgreementPriceLine] PRIMARY KEY NONCLUSTERED (AgreementID, PriceID),
CONSTRAINT [FK_AgreementPriceLine_Agreement]
FOREIGN KEY (AgreementID) REFERENCES Agreement (ID)
ON DELETE NO ACTION ON UPDATE CASCADE,
CONSTRAINT [FK_AgreementPriceLine_PriceID]
FOREIGN KEY (PriceID) REFERENCES Price (ID)
);
Which Entity Framework mapped like so (using generate model from database, the .edmx file):
public partial class Agreement
{
public Agreement()
{
this.Prices = new HashSet<Price>();
}
public virtual ICollection<Price> Prices { get; set; }
}
public partial class Price
{
public Price()
{
this.Agreements = new HashSet<Agreement>();
}
public virtual ICollection<Agreement> Agreements { get; set; }
}
Now, if I want to update two prices on an agreement, how would I go about that? I tried the following:
public void UpdateAgreementPriceLines(List<Price> prices, Agreement agreement)
{
try
{
using (var ctx = new MyEntities())
{
if (agreement != null)
{
// Make sure the number of prices are equal before attempting to "update" anything
if(agreement.Prices.Count == prices.Count)
{
// Clear old prices
agreement.Prices.Clear();
// Add new prices
foreach (var price in prices)
{
agreement.Prices.Add(price);
}
ctx.SaveChanges();
}
}
}
}
catch (Exception e)
{
Logging.Instance.Fatal(e.ToString());
}
}
But it's rather 'hacky' to first empty the collection and then add the new prices. Also, I can't get it to work, the prices are not removed/added at all (and no exception is caught)
Any help/hint on this is greatly appreciated :-)
Thanks in advance.
You need to remove the items from the colletion, like this:
agreement.Prices.Remove(priceItem);
To remove all objects you can do the following:
var prices = agreement.Prices.ToList();
agreement.Prices.RemoveRange(prices);
If you don't want to load all items to the memory before the removal method, you can do the following:
//supposing that you want to deleted the Price which id = 10
Price deletedPrice = new Price { PriceId = 10 };
Context.Entry(deletedPrice).State = EntityState.Deleted;
Context.SaveChanges();

How does Entity framework implement deleting parent and a child record on the ame SaveChanges()

I have the following two entity sets representing Dept & Emp:-
public partial class Dept
{
public Dept()
{
this.Emps = new HashSet<Emp>();
}
public int DeptID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Emp> Emps { get; set; }
}
public partial class Emp
{
public int EmpID { get; set; }
public string Fname { get; set; }
public string Lname { get; set; }
public int DeptID { get; set; }
public virtual Dept Dept { get; set; }
}
Now I wrote this test action method , which will try to delete a dept which have one Emp assigned to it, as follow:-
public ActionResult Test()
{
Dept d = db.Depts.SingleOrDefault(a=>a.id ==1);
Emp e = db.Emps.SingleOrDefault(a => a.id == 100);
db.Entry(d).State = EntityState.Deleted;
db.Emps.Remove(e);
db.SaveChanges();
return Content("done");
}
I thought that an exception will be raised when calling this action method, since the Dept with id=1 already has one emp with id=100. But what happened is that EF has removed the emp first, then the dept. As a final result the above action method, deleted both the dept with id=1 and emp with id =100.. so can you advice on this please? Bearing in mind that if I try to delete the Dept only as follows:
public ActionResult Test()
{
Dept d = db.Depts.SingleOrDefault(a=>a.id ==1);
//Emp e = db.Emps.SingleOrDefault(a => a.id == 100);
db.Entry(d).State = EntityState.Deleted;
//db.Emps.Remove(e);
db.SaveChanges();
return Content("done");
}
I will get the following exception:-
The DELETE statement conflicted with the REFERENCE constraint \"FK_Emp_ToTable\". The conflict occurred in database \"C:\USERS\...\DOCUMENTS\VISUAL STUDIO 2013\PROJECTS\WEBAPPLICATION19\WEBAPPLICATION19\APP_DATA\DATABASE1.MDF\", table \"dbo.Emp\", column 'DeptID'.\r\nThe statement has been terminated."}
So can anyone advice on how EF is implementing these scenarios?
EDIT
i check the sql profiler for my action method and i noted the following 2 delete sql statments:-
exec sp_executesql N'delete [dbo].[Emp]
where ([EmpID] = #0)',N'#0 int',#0=100
exec sp_executesql N'delete [dbo].[Dept]
where ([DeptID] = #0)',N'#0 int',#0=1
so it have deleted the emp first then the dept,, so how EF determine the order , you mentioned it is smart enough to know ,, but what govern this behavior ?
You tried to delete a Dept which has a collection of Emp assigned to it.
The following exception occurred
The DELETE statement conflicted with the REFERENCE constraint
That means that there's a constraint to the Dept - Emp relationship.
My guess is that it's an one - to many relationship, with one Dept being optional to Emp.
I can tell it's optional because the foreign key DeptID is a Nullable<int>.
When you try to delete a Dept, you get an exception because dept is referenced in Emp.
In the first action method you deleted by primary key
Dept d = db.Depts.SingleOrDefault(a=>a.id ==1);
Emp e = db.Emps.SingleOrDefault(a => a.id == 100);
And then used db.Emps.Remove(e); to mark the relationship between as deleted.
If the relationship was optional, Emp would be set to Null using only an SQL Update.
In your case i see two SQL Delete statements were called
The relationship is therefor identifying.
When a primary key of the principal entity is also part of the primary key of the dependent entity, the relationship is an identifying relationship. In an identifying relationship the dependent entity cannot exist without the principal entity. This constraint causes the following behaviors in an identifying relationship:
Deleting the principal object also deletes the dependent object. This is the same behavior as specifying in the model for the relationship.
Removing the relationship deletes the dependent object. Calling the Remove method on the EntityCollection marks both the relationship and the dependent object for deletion.

LINQ-to-Entity Joined Table Return

I have two tables as follows:
Departments:
DeptID (PK)
DeptName
...
Employees:
EmpID (PK)
DeptID (FK)
EmpName
...
and I have a query using LINQ as follows:
public List<Employee> GetEmployee(int deptID)
{
var query = from e in mdc.Employees
join d in mdc.Departments on e.DeptID equals d.DeptID
where e.DeptID == deptID
select new { e.EmpID, e.EmpName, d.DeptName };
return query.ToList();
}
Now my question is this. I would like to select the fields EmpID, EmpName, and DeptName.
But what will my return type be? This one returns an error because this query returns a GenericList as opposed to my List<Employee>.
You need to create another class with required properties like this,
public class NewType{
public EmpID{get;set;}
//other fields here
}
and then select ,
public List<NewType> GetEmployee(int deptID)
{
var query = from e in mdc.Employees
join d in mdc.Departments on e.DeptID equals d.DeptID
where e.DeptID == deptID
select new NewType{ e.EmpID, e.EmpName, d.DeptName };
return query.ToList();
}