I'm facing an issue in fetching data using relationship. Below is the detail:
I'm having two tables. First is item_master and Second is inventory table. Since both are having MANY_MANY relationship, so we are having another table named inventory_items with two fields (item_id, inventory_id).
Below is the relationship detail in ItemMaster Model:
'inventories' => array(
self::MANY_MANY,
'Inventories',
'inventory_items(item_id, inventory_id)'
),
'inventoryItems'=>array(self::HAS_MANY,'InventoryItems','item_id'),
I need to fetch Items of a particular Inventory only. For this, I'm implementing below filter criteria:
$criteria=new CDbCriteria;
$inventory_condition['condition']="inventoryItems.inventory_id=:inventoryID";
$inventory_condition['params'] = array(
':inventoryID' => $filter['inventory_id']
);
$inventory_condition['joinType']='INNER JOIN';
$criteria->with = array("inventoryItems"=>$inventory_condition);
$items=new CActiveDataProvider('ItemMaster',array('criteria'=>$criteria));
Problem:
Above code is returning me all the items with the required inventory. And if an item does not belong to that inventory than still it returns that Item but without inventory. I just need that only those Items should return which belong to a particular inventory.
You probably need to set together option to true:
$inventory_condition['together']=true;
But be careful if you are going to use it with SQL LIMIT.
Related
If I have an array of IDs from a table (table1) in my database. Is there a way of querying another table (table2) to select all the records where a column equals a value equal to one of the IDs from table1.
My code so far is:
LabQuestion.where("product_id=#{Product.where(:brand_id => brand_id).pluck(:id)}")
In this code, I am trying to retrieve all the Lab Questions which are linked to all the products from a brand. This code does not work, but I've tried to demonstrate my needs.
Assuming you have setup your relations properly, you can use joins to join the two tables and query them like this:
LabQuestion.joins(:product).where(:products => { :brand_id => brand_id })
You can use includes instead of joins as below
LabQuestion.includes(:product).where(:products => { :brand_id => brand_id })
I have two entities (Job and Location) that are connected through a many-to-many relationship.
Recently we implemented soft delete logic on the Location entity and then added a filter on the job Mapping like this:
HasManyToMany(x => x.Locations)
.Table("JobLocation")
.ParentKeyColumn("JobId")
.ChildKeyColumn("LocationId")
.ApplyChildFilter<ExcludeDeletedFilter>("IsDeleted = :condition")
.Cascade.None();
The query for the many-to-many relationship looks like this
select ...
from Job job
left outer join JobLocation jl
on jl.JobId = job.Id
left outer join Location loc
on loc.Id = jl.LocationId and IsDeleted = 0
The problem is that now, when fetching a Job that has some deleted locations, the Locations collection on the job entity contains a null entry for each deleted Location.
What is the best way to handle this soft delete records when they are fetched through a many-to-many relationship. (for one to many, this filter does a great job)
What other alternatives should I consider to do this?
Items in a list are associated with an index. When persisted using a list-style mapping, these indices will be preserved (lists normally don't suddenly rearrange themselves).
If you filter some items, to make the visible items have stable positions, it follows that there must be null items for the hidden elements.
Consider using a different mapping, such as a set, bag or map.
I have 3 tables: Topics, Users and Details (those are some of the tables of a custom forum)
Topics contains (among other usual fields) the id (FK) of the user that created the topic.
Users contains nick/pass and id (PK)
Details contains (among other usual fields) the id (FK) of the user.
Relations:
One user can have one 1 detail.
One user can have multiple topics, but a topic can be created only by one user.
Topic relations:
return array(
'user' => array(self::BELONGS_TO, 'User', 'User_iduser'),
);
User relations:
return array(
'details' => array(self::HAS_ONE, 'Details', 'User_iduser'),
);
I'm trying to get a list with Topics and User details (let's say for example the topic name and the user's name).
Currently I have this:
$dataProvider=new CActiveDataProvider('Topic', array(
'criteria'=>array(
'with'=>array('user.details')
)
));
But as you can imagine, it's not working (read as in it's not selecting anything from the tbles Users or Details).
What's wrong with my code?
+++++++++++++++
This code selects fields from the table user (and the topic table):
Topic::model()->with('user')->findAll();
But this one won't select from details, users and topic:
Topic::model()->with('user.details')->findAll();
Also, I need a CActiveDataProvider solution as I need it for zii widgets (means, even if some kind of modification on the Topic::model()->with().... code get's to select from the 3 tables it won't be really helpful)
EDIT: (SQL log from Yii)
Querying SQL: SELECT COUNT(DISTINCT `t`.`idtema`) FROM `tema` `t` LEFT
OUTER JOIN `usuario` `usuarioIdusuario` ON
(`t`.`Usuario_idusuario`=`usuarioIdusuario`.`idusuario`) LEFT OUTER JOIN
`detallesusuario` `detallesusuario` ON
(`detallesusuario`.`Usuario_idusuario`=`usuarioIdusuario`.`idusuario`)
Querying SQL: SELECT `t`.`idtema` AS `t0_c0`, `t`.`Usuario_idusuario` AS
`t0_c1`, `t`.`Categoria_idcategoria` AS `t0_c2`, `t`.`tema` AS `t0_c3`,
`t`.`fecha_hora` AS `t0_c4`, `usuarioIdusuario`.`idusuario` AS `t1_c0`,
`usuarioIdusuario`.`nick` AS `t1_c1`, `usuarioIdusuario`.`contrasena` AS
`t1_c2`, `usuarioIdusuario`.`email` AS `t1_c3`,
`detallesusuario`.`Usuario_idusuario` AS `t2_c0`,
`detallesusuario`.`nombre` AS `t2_c1`, `detallesusuario`.`apellidos` AS
`t2_c2`, `detallesusuario`.`cumpleanos` AS `t2_c3`,
`detallesusuario`.`telefono1` AS `t2_c4`, `detallesusuario`.`telefono2` AS
`t2_c5` FROM `tema` `t` LEFT OUTER JOIN `usuario` `usuarioIdusuario` ON
(`t`.`Usuario_idusuario`=`usuarioIdusuario`.`idusuario`) LEFT OUTER JOIN
`detallesusuario` `detallesusuario` ON
(`detallesusuario`.`Usuario_idusuario`=`usuarioIdusuario`.`idusuario`)
LIMIT 10
Try this
$dataProvider=new CActiveDataProvider('Topic', array(
'criteria'=>array(
'with'=>array('user'=>array('alias'=>'user','with'=>array('details'=>array('alias'=>'details'))))
)
));
And
Topic::model()->with(array('user'=>array('alias'=>'user','with'=>array('details'=>array('alias'=>'details')))))->findAll();
instead of the line
'with'=>array('user.details')
use
'with'=>array('user')
then add
$criteria->compare( 'user.details', $query, true );
$criteria->together = true;
}
*Where $query is a variable that will be searched in column details
I am using linqpad. I have an ODATA connected. The entities are listed in left pane with relationships. There are two entities called Products and Customers. I have to get all the product id starting with pid and names of all customers startin with b. There is a relationship between both. Product is a child of customer. How do I do? I am trying since two days but unable to figure it out. Anyone could help?
this is the base code. i dont no what to do further.
from p in products
where p.ProductId.StartsWith("Pid")
from c in customers
where c.Name.StartsWith("B")
select new
{
p.Pid,
c.Name
};
Can you please specify how you want the relation between the two entities to affect the result of the query? Do you expect the above to only returns products (with ID starting with a given value) and then only the customers for those products which name starts with a certain value?
Such a query is not expressible in OData unfortunately. You could request all products which ID starts with a specific value, and all the related customers. And then filter the customers on the client.
For example this will get you all the products which ID starts with a certain value and all their customers:
from p in products
where p.ProductId.StartsWith("Pid")
select new Product
{
ProductId = p.ProductId,
Customers = p.Customers
};
I am using Entity Framework 4.1 using the Code First approach. I have two entities that exhibit a parent-child relationship. To provide a concrete example, imagine I have a Category entity that has zero-to-many Product entities associated with it. I have set up navigation properties on both sides (in my example, the Category entity would have an ICollection<Product> property while the Product entity has a Category property).
Now, when I get Category entities I want to also get back a count of the number of children records for each category. I am aware I can do:
Category category = dbContext.Categories.Single(...);
int productCount = category.Products.Count();
But I am concerned because the resulting SQL that gets sent to the database depends on whether I use lazy or eager loading.
In the first case (lazy loading), the call to the Products collection prompts EF to run a SQL query like:
SELECT ... all columns ...
FROM Products
WHERE CategoryID = #CategoryID
In the second case (eager loading), the products are loaded when the category information is retrieved so there is no second query to the database, but the downside is that if I'm not at all interested in products (other than their count) then I'm bringing back a lot of unneeded data.
What I'd like it to have the best of both worlds: namely, the ability to have just one database query and one that uses SELECT COUNT(*) rather than one that gets all of the columns from the table. In short, I'd like SQL like the following to be sent to the database:
SELECT ... all category columns ...,
(SELECT COUNT(*) FROM Products p WHERE p.CategoryID = c.CategoryID)
FROM Categories c
WHERE c.CategoryID = ...
Is that at all possible with EF or is what I want a pipe dream?
Not sure, but maybe try this:
var result = db.Categories.Where(x => x.CategoryId == categoryId)
.Select(y => new
{
Count = y.Products.Count(),
Category = y
})
.Single();
//result.Count
//result.Category
Yes, this is possible with EF. You can also create a view model to show the information with the child counts as properties. This article cover how to do that.
http://www.ozkary.com/2015/04/entity-framework-associated-table.html