I have the following classes:
public class Configuration
{
public long Id {get;set;}
public string Name {get;set;}
public Expression Criteria {get;set;}
}
public class Expression
{
public long Id {get;set;}
public string Value {get;set;}
public ICollection<Parameter> Parameters {get;set;}
}
public class Parameter
{
public long Id {get;set;}
public MyType Type {get;set;}
}
public class MyType
{
public long Id {get;set;}
public string Name {get;set;}
}
I am trying to eagerly load the entire configuration object using:
dbContext.Configurations.Select(i => i.Criteria).Include(i => i.Parameters.Select(j => j.Type)).ToList()
I am however getting null for the Parameters property and it is not getting fetched.
What am I doing wrong.
Try this:
dbContext.Configurations.Select(i => i.Criteria).Include("Parameters").Include("Parameters.Type").ToList()
Related
I have three classes
public class Country
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public byte CountryID { get; set; }
public byte OfficialLangID { get; set; }
}
public class Language
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public byte LangID { get; set; }
}
public class Name
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public byte NameID { get; set; }
public bool isLanguage { get; set; } // true for language - false for country
public byte FK { get; set; } // FK=LangID or CountryID
}
Now I want to create Navigation properties:
Country.Name
Language.Name
Name.Language
Name.Country
I want to do it in this way for many reasons, one of them to search for all the names in one table without joining.
Please don't suggest another way,I want navigation properties for my way.
why you're doing it like this? putting a boolean field to check the type of the entity here doesn't make any sense? in the end, the ef framework will create 2 tables.
here is my approach:
public class Country
{
public byte Id {get;set;}
public string Name {get;set;}
public int LanguageId {get;set;}
}
public class Language
{
public byte Id {get;set;}
public string Name {get;set;}
// assuming that each language may have one or many countries
public ICollection<Country> Countries {get;set;}
}
ef core here will create the tables and the relations automatically. now if you see some code duplications (like I've understood), that the 2 entities use the same field types and names, here is what you can do
public abstract class EntityBase
{
public byte Id {get;set;}
public string Name {get;set;}
}
now inherit this abstract class to the entity class
public class Country : EntityBase
{
public int LanguageId {get;set;}
}
public class Language : EntityBase
{
public ICollection<Country> Countries {get;set;}
}
What is the solution to manage Entity code first zero or one to zero or one relationship ?
I would like to have a nav property on the two entities.
I already test with data annotation :
public class class1()
{
public int Id {get;set;}
public virtual Class2 Class2 {get;set;}
}
public class class2()
{
public int Id {get;set;}
public int? Class1Id {get;set;}
[Required, ForeignKey("Class1Id")]
public Class1 Class1 {get;set;}
}
I always have an error message : "Class1_Class2_Target: : Multiplicity is not valid in Role 'Class2_Class1_Target' in relationship 'Class2_Class1'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'".
I found samples with fluent API but if it's possible I would like to use data annotations. Indeed, for all examples using fluent api there is a navigation property but the int foreign key is deleted from the class :
class Class1Map : EntityTypeConfiguration<Class1>
{
public Class1Map()
{
this.HasKey(c => c.Id);
this.Property(c => c.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
this.HasRequired(c1 => c1.Class2).WithRequiredPrincipal(c2 => c2.Class1);
}
}
public class Class1()
{
public int Id {get;set;}
public virtual Class2 Class2 {get;set;}
}
public class Class2()
{
public int Id {get;set;}
/* Missing Class2Id Property */
public virtual Class1 Class1 {get;set;}
}
There are tons of articles about this, so I suggest you read this article and Google around a little bit further before asking such general questions.
I have a simple project in which i have the following model.
Customer 1--->N Addresses N<----1 City N<----1 Country
^
N|
|
AddressTypes 1-------+
Here is my code:
public partial class Customer {
public Customer() {
this.Address = new HashSet<Address>();
}
public int Id {get;set;}
public string FirstName {get;set;}
public string LastName {get;set;}
public System.DateTime Birthday {get;set;}
public virtual ICollection<Address> Address {get;set;}
}
public partial class Address {
public int Id {get;set;}
public string Street {get;set;}
public string Area {get;set;}
public string Post {get;set;}
public bool isDeleted {get;set;}
public virtual Customer Customer {get;set;}
public virtual City City {get;set;}
public virtual AddressType AddressType {get;set;}
}
public partial class AddressType {
public AddressType() {
this.Address = new HashSet<Address>();
}
public int Id {get;set;}
public string Name {get;set;}
public virtual ICollection<Address> Address {get;set;}
}
public partial class Country {
public Country() {
this.City = new HashSet<City>();
}
public int Id {get;set;}
public string Name {get;set;}
public virtual ICollection<City> City {get;set;}
}
public partial class City {
public City() {
this.Address = new HashSet<Address>();
}
public int Id {get;set;}
public string Name {get;set;}
public virtual ICollection<Address> Address {get;set;}
public virtual Country Country {get;set;}
}
public partial class MyModelContext : DbContext {
public MyModelContext()
: base("name=MyModelContext") {
this.Configuration.LazyLoadingEnabled = true;
this.Configuration.ProxyCreationEnabled = false;
}
public virtual DbSet<Country> Countries {get;set;}
public virtual DbSet<City> Cities {get;set;}
public virtual DbSet<AddressType> AddressTypes {get;set;}
public virtual DbSet<Address> Addresses {get;set;}
public virtual DbSet<Customer> Customers {get;set;}
}
I want to return a list of customers. At first i tried to do a simple Customers.ToList() but i was getting an exception during serialization and i read that this was caused by cyclical references. So i added
Configuration.LazyLoadingEnabled = true;
Configuration.ProxyCreationEnabled = false;
and then i was able to get the customers but without the addresses. I tried doing:
public List<Customer> getCustomers() {
MyModelContext db = new MyModelContext();
return db.Customers.Include("Address").ToList();
}
but i don't know how to retrieve ALL the properties. I want to get in the list every customer and his addresses including the city, country, addresstype of each address. How can i do it?
You have couple of options:
1. Use DTOs (Data Transfer Objects).
2. Explicitly ignore the problematic property that contains the circular references to the parent object by applying the below Attributes:
// in Address entity
[IgnoreDataMember]
[XmlIgnore]
[NonSerialized]
public Customer Custom { get; set; }
Also in AddressType.Address, City.Address, and Country.City.
3. Project your entities into anonymous objects and exclude the pr:
db.Customers.Select(c => new
{
c.Id,
c.FirstName,
c.LastName,
c.Birthday,
Address = c.Address.Select<Address, object>(a => new
{
a.Id,
AddressType = new
{
a.AddressType.Id,
a.AddressType.Name
},
a.Area,
City = new
{
a.City.Id,
Country = new
{
a.City.Country.Id,
a.City.Country.Name
},
a.City.Name,
},
a.Post,
a.Street,
a.isDeleted
}),
});
You'll have to turn LazyLoadingEnabled and ProxyCreationEnabled back on in order for it to work (or use Include).
(As a side note, i don't really understand why you need this circular references at all, what benefit do you get from AddressType.Address?)
I solved it this way:
public List<Customer> getCustomers() {
var customers = db.CustomerSet.Include("Address")
.Include("Address.AddressType")
.Include("Address.City")
.Include("Address.City.Country")
.ToList();
return customers;
}
i don't really like that i have to explicitly write all the properties of the customer and there is not a generic way of doing what i want but it works.
I would like to set up something like below as it is a cleaner POCO design, but it seems that I can only make this work by creating a UserId property of int instead of the lazily loaded POCO.
[Route("/Accounts", "GET")] //Where I want to be able to do /Accounts?UserId=1234
[Route("/Accounts/{Id}", "GET")]
public class Account
{
public User User {get;set;}
public int Id {get;set;}
...
}
public class User
{
public int Id {get;set;}
...Lazily loaded values
}
Is this the only option?
public class Account
{
public int UserId {get;set;}
public int Id {get;set;}
...
}
Is the Account class your request dto? See the wiki to see how to decorate your request dto with routes, https://github.com/ServiceStack/ServiceStack/wiki/Routing
I created classes:
public class Country
{
public long CountryId {get;set;}
public string CountryName {get;set;}
}
public class Profile
{
public long ProfileId {get;set;}
public string ProfileName {get;set;}
public Country Country {get;set;}
}
and configuration for Profile:
public class ProfileConfiguration : EntityConfiguration<Profile>
{
public IlluminatiCoreProfileConfiguration()
{
Relation(p => p.Country);
}
}
Then I create context and run context.CreateDatabase(). New database contains table Profiles with column Country_CountryId. How can I write configuration for changing column name to "CountryId"?
Thanks.
In your POCO for Profile:
public class Profile
{
public long ProfileId {get;set;}
public string ProfileName {get;set;}
[ForeignKey("CountryId")]
public Country Country {get;set;}
}
In your POCO for Country
[Table("Country")]
public class Country
{
[Column(Name = "CountryId")]
public int CountryId {get;set;}
}
This will over write the brain dead Object_Property mapping that EF by default creates. You can specify this on any table / property to override the actual DB column naming conventions.
EDIT:
I guess the namespace for those annotations would be helpful:
using System.ComponentModel.DataAnnotations;