If I have a DB structure like this
class Parent {
int ID { get; set; }
string Name { get; set; }
List<Child> Children { get; set; }
}
class Child {
int ID { get; set; }
string Name { get; set; }
List<Parent> Parents { get; set; }
}
I want to get a list of all the Parents who have a child whos name is NOT "Dave"
So
If Parent one has two children called Jack and Jill, I want them
If Parent two has two children called Sam and Dave I dont want them
If Parent three has no children I want them
If Parent four has one child called Steve I want them
If Parent five has one child called Dave, I dont want them
I want to get a list of all the Parents who have a child whos name is NOT "Dave"
conflicts with Rule #3: If Parent three has no children I want them.
The requirement that fits all the rules can be described as:
get a list of all the Parents who have NO child WITH name "Dave"
which in LINQ translates as:
var query = db.Parent.Where(p => !p.Children.Any(c => c.Name == "Dave"));
Related
I'm trying to add some logic into the BeforeSaveEntities method.
On the client we can add a parent record and a number of child records before hitting save.
Our parent record has two fields which can be chosen by the user and are a sort of unique identifier (but not the id). The child record also has some unique identifiers and a total field. The classes look something like this:
public class Parent
{
public int Id { get; set; }
public int Ref1 { get; set; }
public int Ref2 { get; set; }
public virtual ICollection<Child> Children { get; set; }
}
public class Child
{
public int Id { get; set; }
public int Ref1 { get; set; }
public int Ref2 { get; set; }
public int Total { get; set; }
public int ParentId { get; set; }
[ForeignKey("ParentId")]
public Parent Parent { get; set; }
}
In the BeforeSaveEntities I'm trying to check if a parent record with the Ref1 and Ref2 fields the same as the added entity using a second context.
If a parent record exists, I remove it from the savemap to prevent it from being re-added (this seems to work).
I then look at the child records being added (again by querying a second context), and what I'm trying to do is allow the new record to be added by leaving them in the savemap where they don't exist (but updating the parentid to link them to the existing parent record).
If a child record already exists, I want to increment the total of the existing record by the value in the added one in the savemap.
I've tried a couple of ways, but can't seem to get it working. It always seems to result in all child entries for the parent getting added again, even if there is only one new child entity in the savemap.
Apologies for the contrived classes, but hopefully this gives enough info to convey what I'm trying to do.
Is there any way to save a child object in a parents child object collection and also setting it to a navigation property on the parent without round tripping to the database? example below doesn't work
public class Parent
{
int Id { get; set; }
int? ChildId { get; set; }
Child Child { get; set; }
public virtual ICollection<Child> Children { get; set; }
}
public class Child
{
int Id { get; set; }
public Parent Parent { get; set; }
}
....
var p = new Parent();
var c = new Child();
p.Child = c;
p.Children.Add(c);
Context.Set<Parent>().Add(p);
Context.SaveChanges();
EDIT
The example above throws this error when 'savechanges()' is called.
Unable to determine a valid ordering for dependent operations. Dependencies may exist due to foreign key constraints, model requirements, or store-generated values.
Given something like:
public class Parent
{
public int Id { get; set; }
public List<Child> Children { get; set; }
}
// There is no reference to the parent in the object model
public class Child
{
public int Id { get; set; }
public string MyProperty { get; set; }
}
is it possible to load only a child matching a particular condition, for a given Parent ID, without also loading the parent entity?
I have seen solutions that use projection to load the parent and zero or more children matching a condition.
If I understand you correctly, this should do it; it puts the conditions you want on both the parent and child, but selects only the child.
from parent in db.Parents
from child in parent.Children
where parent.Id = 4711 &&
child.MyProperty == "olle"
select child;
Read it several times and understood that i'm not so good in asking questions correctly. Made some corrections to the question.
I have 2 classes in my app: Contractor and ContractorGroup.
Each Contractor has a parent Contractor. Parent Contractor can see only it's dependants. And can not see dependants of it's dependants. Only one level of visibility.
Parent Contractor can group it's dependant Contractors into ContractorGroup.
So, many dependant Contractors for one ContractorGroup (many-to-one)
Contractor has a NavProperty ContractorGroup, the group to which it belongs. Each Contractor can be ONLY IN ONE ContractorGroup.
Example:
I'm the parent Contractor and have 5 dependant Contractors and i want to group first 2 of them into 1stContractorGroup and last 3 to 2ndContractorGroup.
So, options to implement:
First: I can not to include FK(VisibleToContractorId - id of my parent Contractor) in ContractorGroup which connects each of 2 groups to parent Contractor.
In this case i can do query similar to:
var ContractorGroupsToDispalayForParentContractor =
context.ContractorGroups.Where(p => p.Contractors.All(p => p.Parent == ParentContractor));
In other words: "Find all groups which consist of contractors with parent == ParentContractor"
In this option everything works fine. DbSchema is simple and clear. But i dont like the query.
Second: Or i can introduce FK(VisibleToContractorId). So one parent Contractor has many ContractorGroups which consist of dependant Contractors. Then i have a simplier and more robust query:
var ContractorGroupsToDispalayForParentContractor =
context.ContractorGroups.Where(p => p.VisibleToContractor == ParentContractor);
This query i like. But EF introduces strange DbColumn which is ALWAYS null. >:-E
Short db schema:
Table("Contractor")
ContractorId = PK
ContractorGroupId = FK
ContractorGroup_ContractorGroupId = FK <--- This One
Table("ContratorGroup")
ContractorGroupId = PK
VisibleToContractorId = FK
My domain Classes and EntityConfiguration:
public class Contractor : IObjectWithState
{
[Key]
public virtual int ContractorId { get; set; }
public virtual Contractor Parent { get; set; }
public virtual int? ParentId { get; set; }
public virtual ContractorGroup ContractorGroup { get; set; }
public virtual int? ContractorGroupId { get; set; }
public virtual ICollection<ContractorGroup> GroupsVisible { get; set; }
}
public class ContractorGroup : IObjectWithState
{
[Key]
public virtual int ContractorGroupId { get; set; }
public virtual Contractor VisibleToContractor { get; set; }
public virtual int? VisibleToContractorId { get; set; }
public virtual ICollection<Contractor> Contractors { get; set; }
}
Entity configurations (only in ContractorGroupConfiguration):
HasMany(p => p.Contractors).WithOptional(p=>p.ContractorGroup);
HasOptional(p => p.VisibleToContractor).WithMany(
p=>p.GroupsVisible).HasForeignKey(p=>p.VisibleToContractorId);
Is it a bug in EF?
What implementation First or Second of domain model would you prefer?
Thanks.
The point is that you need to tell EF that the associations ContractorGroup.VisibleToContractor and Contractor.GroupsVisible are no independent associations (with two FK fields), but are two parts of a bidirectional association. Replace the entity configurations by:
class ContractorConfiguration : EntityTypeConfiguration<Contractor>
{
public ContractorConfiguration()
{
HasMany(c => c.GroupsVisible).WithOptional(g => g.VisibleToContractor);
}
}
Without this, EF creates the field ContractorGroup_ContractorGroupId as a FK for Contractor.GroupsVisible on top of the FK VisibleToContractorId.
i have the following model.
class Parent
{
int ParentId (identity column) { get; set; }
string ParentName { get; set; }
virtual ICollection<Child> Children { get; set; }
}
class Child
{
int ChildId (identity column) { get; set; }
string ChildName { get; set; }
int ParentID { get ; set; } //foreign key to Parent(ParentID)
}
How do i insert few rows to my parent and child in single transaction? Basically i want to get the identity generated on the parent(say i insert a row in parent) and insert child rows with that value?
How this can be achieved using Code First?
You shouldn't worry about what value the Id of Parent will get in order to insert Child rows. This should be enough:
var parent = new Parent
{
// fill other properties
Children = new List<Child>()
}
parent.Children.add(new Child { /*fill values */);
dbContext.Parents.Add(parent); // whatever your context is named
dbContext.SaveChanges();
For the record, the ID's will be assigned after calling SaveChanges(), so if you really need the ID before inserting a Child entity you can always call SaveChanges() twice.
Again, this shouldn't be necessary though.
By the way, I would recommend making the Foreign Key property from Child to Parent a navigation property, so the Child class would look like:
class Child
{
public int ChildId { get; set; } // identity column
public string ChildName { get; set; }
public virtual Parent Parent { get ; set; } //foreign key to Parent
}
That way you can always access the Child's parent directly without having to retrieve it explicitly from the database yourself (it will be lazy loaded).
For an example of how to do this, see the new EF Code First MVC tutorial series. The 6th one in the series has an example of this. The first one in the series of 10 is here:
http://www.asp.net/entity-framework/tutorials/creating-an-entity-framework-data-model-for-an-asp-net-mvc-application