I have the following models which represent my table relationship.
public class A { List<B> B_List }
public class B { public int amount }
I was wondering if it is possible to get top 5 class A objects order by "amount".
I was hoping there is a way to write an EF query to avoid pulling all A objects from database.
I think #Bilal's answer is close, but may not get you exactly what you want. By the way, you haven't been clear on what you mean by "top 5 A objects order by Amount". Each A object has multiple amounts. Are you wanting the top 5 A objects based on the maximum amount? If so, then try this ...
dbContext.AList
.OrderByDescending(a => a.B_List.Sum(b => b.amount))
.Take(5);
Related
Following the guide lines from Domain Driven Design, I try to avoid having one aggregate referencing a different aggregate. Instead, an aggregate should reference another aggregate using the other aggregate's id, for example:
public class Addiction
{
private Addiction(){} //Needed for EF to populate non-simple types
//DrugType belongs to the aggregate,
//inflate when retrieving the Addiction from the db
//EF does not need DrugId for navigation
Drug Drug{get;set;}
//The supplier is not part of the aggregate,
//aggregates only reference eachother using Ids
int SupplierId{get;set;}
//Other properties
}
public class AddictionConfiguration : IEntityTypeConfiguration<Addiction>
{
builder.HasOne(addiction => addiction.Drug); //Works
builder.HasOne("SupplierId") //Does not work.
}
In this (not very realistic) example, Drug is part of the Addiction's aggregate. When loading this entity from the database using EF, it will also inflate the Drug property without me having to specify the DrugId as the foreign key.
However, now I need to get a list of all Addictions and their suppliers by mapping the relevant properties to a Dto. I try to achieve this by using AutoMapper's ProjectTo functionality, e.g.
_mapper.ProjectTo<AddictionDto>(_dbContext.Addictions.Where(x => x.Id > 1));
where AddictionDto is defined as
public class AddictionDto
{
DrugDto Drug {get;set;}
SupplierDto Supplier {get;set;}
//other properties
}
And
public class SupplierDto
{
public int Id {get;set;}
public string Name {get;set;}
}
Automapper correctly loads the Addiction and also the Drug, but I cannot get it to load the Supplier. I've tried all the options of the IEntityTypeConfiguration to tell EF that there is a navigation property, but I cannot get it to work. Does anyone know if is even possible to do what I described above?
Is there a way to create a one to one-or-more relationship in Entity Framework? I've seen plenty examples showing a 1 to 0..* relationship, but I want to be sure that in the given example Foo can only exist if it has at least one Bar.
class Foo
{
List<Bar> Bars { get; set; }
}
class Bar
{
public Foo Foo { get; set; }
}
I see that this is not easily achieved by SQL since I want a kind of NOT NULL at the Foo table instead of at the Bar table, but can Entity Framework handle this?
I realized I asked the wrong question, since I was in fact looking for a 0..1 to 1..* relationship, which is significantly different. This is the question I meant to ask.
It's impossible to have a true 1 to 1 relationship in any SQL database that i'm aware of. While Set theory allows for a 1 to 1, in practicality, this is difficult to implement.
It's basically a chicken and egg situation. You can't create Foo because you don't have a Bar, and you can't create Bar because there is no Foo yet. The constraints required to create a 1 to 1 essentially prevent you from inserting any actual rows.
Now, you could disable constraints, insert the data and then re-enable them, but that's a hacky kludge that really defeat the purpose of having constraints in the first place.
So just accept the 1 to 0..* and move on.
As close as you can get is something like this:
class Foo
{
List<Bar> Bars { get; set; }
[Required]
public int PrimaryBarId { get; set; }
public Bar PrimaryBar { get; set; }
}
class Bar
{
public Foo Foo { get; set; }
}
But note that the database will not enforce
aFoo.PrimaryBar.FooId == aFoo.Id
And this kind of model is tricky to update because of the circular FKs.
The difficulties of implementing such a solution and the possibilities are discussed in the example below.
Mapping one-to-one
Mapping one-to-one (when both sides are required) is also a tricky thing.
Let's imagine how this could be represented with foreign keys. Again, a CarId in People that refers to CarId in Car, and a PersonId in Car that refers to the PersonId in People.
Now what happens if you want to insert a car record? In order for this to succeed, there must be a PersonId specified in this car record, because it is required. And for this PersonId to be valid, the corresponding record in People must exist. OK, so let's go ahead and insert the person record. But for this to succeed, a valid CarId must be in the person record — but that car is not inserted yet! It cannot be, because we have to insert the referred person record first. But we cannot insert the referred person record, because it refers back to the car record, so that must be inserted first (foreign key-ception :) ).
So this cannot be represented the 'logical' way either. Again, you have to drop one of the foreign keys. Which one you drop is up to you. The side that is left with a foreign key is called the 'dependent', the side that is left without a foreign key is called the 'principal'. And again, to ensure the uniqueness in the dependent, the PK has to be the FK, so adding an FK column and importing that to your model is not supported.
So here's the configuration:
public class CarEntityTypeConfiguration : EntityTypeConfiguration<Car>
{
public CarEntityTypeConfiguration()
{
this.HasRequired(c => c.Person).WithRequiredDependent(p => p.Car);
this.HasKey(c => c.PersonId);
}
}
By now you really should have gotten the logic of it :) Just remember that you can choose the other side as well, just be careful to use the Dependent/Principal versions of WithRequired (and you still have to configure the PK in Car).
public class PersonEntityTypeConfiguration : EntityTypeConfiguration<Person>
{
public PersonEntityTypeConfiguration()
{
this.HasRequired(p => p.Car).WithRequiredPrincipal(c => c.Person);
}
}
If you check the DB schema, you'll find that it's exactly the same as it was in the case of the one-to-one or zero solution. That's because again, this is not enforced by the schema, but by EF itself. So again, be careful :)
Suppose I have a class Parent, with two subclasses, AChild and BChild. I have these mapped to a single table using Entity Framework 5.0.0 on .NET 4.5, using TPH.
public abstract class Parent {
public string Type { get; set; } // Column with this name in DB is discriminator.
public string Status { get; set; }
}
public class AChild : Parent {
// Other stuff.
}
public class BChild : Parent {
// Other stuff.
}
The code to configure the mapping:
class ParentConfiguration : EntityTypeConfiguration<Parent> {
Map((EntityMappingConfiguration<AChild> mapping) => mapping
.Requires("Type")
.HasValue("A"));
Map((EntityMappingConfiguration<BChild> mapping) => mapping
.Requires("Type")
.HasValue("B"));
}
I have a need to run a query that returns both AChild and BChild objects. However, it needs to filter ONLY the AChild rows by a second column, which in this example I will call Status.
Ideally I would want to do the following:
public IList<Parent> RunQuery() {
IQueryable<Parent> query =
this.context.Set<Parent>()
.Where((Parent parent) => !parent.Type.Equals("A") || parent.Status.Equals("Foo"))
.OrderBy((Parent parent) => parent.Number);
return query.ToList();
}
This doesn't work. It insisted on looking for a "Type1" column instead of just letting both the discriminator and a "Type" property be mapped to the same "Type" column.
I know of the "OfType" extension method that can be used to completely filter down to one type, but that's too broad a brush in this case.
I could possibly run multiple queries and combine the results, but the actual system I'm building is doing paging, so if I need to pull back 10 rows, it gets messy (and inefficient) to query since I'll either end up pulling back too many rows, or not pull back enough and have to run extra queries.
Does anyone have any other thoughts?
There are few problems. First of all you cannot have discriminator mapped as a property. That is the reason why it is looking for Type1 column - your Type property results in second column because the first one is already mapped to .NET types of your classes. The only way to filter derived types is through OfType.
The query you want to build will be probably quite complex because you need to query for all Bs and concatenate them with result of query for filtered As. It will most probably not allow you to concatenate instances of Bs with As so you will have to convert them back to parent type.
First of I am new to ORMLite. I would like my model class to have a field which is a list of strings, that would eventually hold a list of tags for my model object.
Which ORMLite annotations should I use?
Firstly I don't want to have a table of all tags, and then use the #ForeignCollectionField.
Also I thought of using the #DatabaseField(dataType=DataType.SERIALIZABLE) annotation, but it turns out that List<String> doesn't implement the Serializable interface.
What are your suggestions?
First of all, List doesn't implement Serializable but ArrayList certainly does as well as most of the common collection implementations. But storing a huge list is probably not the best of doing this from a pure object model standpoint.
So why don't you want to have a table of all tags? That's the best way from a pure model standpoint. It will require a 2nd query if you need them every time. That's the way hibernate would store a list or array of tags.
After reading your comment #creen, I still think you do want a table of tags. Your model class would then have:
#ForeignCollectionField
Collection<Tag> tags;
The tags table would not have a single tag named "red" with multiple model classes referring to it but multiple "red" entries. It would look like:
model_id name
1 "red"
1 "blue"
2 "red"
3 "blue"
3 "black"
Whenever you are removing the model object, you would first do a tags.clear(); which would remove all of the tags associated with that model from the tags table. You would not have to do any extra cleanup or anything.
No need to go for #ForeignCollectionField for simple String Array
Change your code
#DatabaseField(dataType=DataType.SERIALIZABLE)
List<String> users;
to
#DatabaseField(dataType = DataType.SERIALIZABLE)
String[] users;
Database doesn't want to store dynamically grow able arrays. That is the reason it allows only static array like string[] and not List.
I added two properties... one that gets written to the database as a csv string and the other that translates this:
[Ignore]
public List<string> Roles
{
get
{
return new List<string>(RolesCsv.Split(new char[] { ',' }));
}
set
{
RolesCsv = string.Join(",", value);
}
}
public string RolesCsv { get; set; }
I implemented inheritance with a discriminator field so all my records are in the same table. My basetype is Person (also the name of the table) and Driver and Passenger inherit from it. I receive instances of the correct type (Driver and Passenger) when I perform a query on the object context to Person. example:
var q = from d in ctx.Person
select d;
But I also create a function that calls a stored procedure and mapped the output of the function to the type Person. But now I get a list of Person and not Drivers or Passengers when I execute this method.
Anybody an idea how to solve this or is this a bug in EF4?
AFAIK, you can't use discriminator mapping (e.g TPH) when dealing with stored procedure mappings.
The stored procedure must be mapped to a complex type or custom entity (e.g POCO), the mapping cannot be conditional.
What you could do is map it to a regular POCO, but then project that result set into the relevant derived type (manual discrimination).
E.g:
public ICollection<Person> GetPeople()
{
var results = ExecuteFunction<Person>(); // result is ObjectResult<Person>
ICollection<Person> people = new List<Person>();
foreach (var result in results)
{
if (result.FieldWhichIsYourDiscriminator == discriminatorForDriver)
{
people.Add((Driver)result);
}
// other discriminators
}
}
If your always expecting a collection of one type (e.g only Drivers), then you wouldn't need the foreach loop, you could just add the range. The above is in case you are expecting a mixed bag of different people types.
Would be interested to see other answers, and if there is a better way though - but the above should work.