In the MSDN they show how to implement EF TPT with this example:
public abstract class BillingDetail
{
public int BillingDetailId { get; set; }
public string Owner { get; set; }
public string Number { get; set; }
}
[Table("BankAccounts")]
public class BankAccount : BillingDetail
{
public string BankName { get; set; }
public string Swift { get; set; }
}
[Table("CreditCards")]
public class CreditCard : BillingDetail
{
public int CardType { get; set; }
public string ExpiryMonth { get; set; }
public string ExpiryYear { get; set; }
}
public class InheritanceMappingContext : DbContext
{
public DbSet<BillingDetail> BillingDetails { get; set; }
}
Regarding (*) I have this question:
Can I have a DbSet per child in the hierarchy? ie:
public class InheritanceMappingContext : DbContext
{
public DbSet<BankAccount> BankAccount { get; set; }
public DbSet<CreditCard> CreditCards{ get; set; }
}
I'm asking this because I'd like to have a main father class from which all the other classes inherit, ie:
public abstract class DatabaseItem
{
[Key]
public long DatabaseItemId { get; set; }
}
public User : DatabaseItem
{
...
}
public Picture : DatabaseItem
{
...
}
public Gallery : DatabaseItem
{
...
}
So that given an ID, I know that it corresponds to only one thing.
In the past in other projects I didnt do this, and used specifical IDs: "UserId", "PictureId", "GalleryId".
In this case, I will be having only one DbSet?
DbSet<DatabaseItem> DatabaseItems
Related
I want to use a FromSqlRaw query with view models and inheritance between them.
I created two example view models:
public class SummaryVM
{
public int Quantity { get; set; }
public int Value { get; set; }
}
public class DistrictVM : SummaryVM
{
public string DistrictName { get; set; }
}
My DbContext has this content:
public DbSet<SummaryVM> SummaryVMs { get; set; }
public DbSet<DistrictVM> DistrictVMs { get; set; }
...
modelBuilder.Entity<SummaryVM>().HasNoKey();
My query:
return await _context.DistritVMs.FromSqlRaw(query).ToListAsync();
but I get an error:
SqlException: Invalid column name 'Discriminator'. Invalid column name 'DistrictName'
I know this is due to the TPH pattern and I can solve this problem if I do not use inheritance yet how I can use these two tables with inheritance without TPH, please?
SOLUTION
I had to create a base class which is not registered as entity:
public abstract BaseClass
{
public int Quantity { get; set; }
public int Value { get; set; }
}
public class SummaryVM : BaseClass
{
}
public class DistrictVM : BaseClass
{
public string DistrictName { get; set; }
}
SOLUTION
I had to create a base class which is not registered as entity:
public abstract BaseClass
{
public int Quantity { get; set; }
public int Value { get; set; }
}
public class SummaryVM : BaseClass
{
}
public class DistrictVM : BaseClass
{
public string DistrictName { get; set; }
}
I want to realize structure like this:
public enum TreeType {
Product = 1,
User = 2,
Document = 3
}
public enum ProductType {
Service = 1,
Ware = 2
}
public enum DocumentType {
Order = 1,
Invoice = 2
}
public abstract class Tree
{
[Key]
public Guid Id { get; set; }
[Required]
public string Name { get; set; }
[NotMapped]
public TreeType Type { get; set; }
}
public abstract class Product : Tree
{
[Required]
public string Article { get; set; }
[NotMapped]
public ProductType ProductType { get; set; }
public Tree
{
this.Type = TreeType.Product;
}
}
public class User : Tree
{
[Required]
public string Login { get; set; }
[Required]
public string Password { get; set; }
public User
{
this.Type = TreeType.User;
}
}
public abstract class Document : Tree
{
[Required]
public int PageCount { get; set; }
[Required]
public DateTime Created { get; set; }
[NotMapped]
public DocumentType DocumentType { get; set; }
public Document
{
this.Type = TreeType.Document;
}
}
public class Service : Product
{
[Required]
public int VisitCount { get; set; }
public Service
{
this.ProductType = ProductType.Service;
}
}
public class Ware : Product
{
[Required]
public string StorageName { get; set; }
public Ware
{
this.ProductType = ProductType.Ware;
}
}
public class Order : Document
{
[Required]
public string CustomerName { get; set; }
public Order
{
this.DocumentType = DocumentType.Order;
}
}
public class Invoice : Document
{
[Required]
public string SupplierName { get; set; }
public Invoice
{
this.DocumentType = DocumentType.Invoice;
}
}
public class TreeDbContext : DbContext
{
DbSet<Tree> Trees { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Tree>().ToTable("L_TREES");
.Map<Product>(x => x.Requires("Type").HasValue((int)TreeType.Product)).ToTable("L_PRODUCTS");
.Map<User>(x => x.Requires("Type").HasValue((int)TreeType.User)).ToTable("L_USERS");
.Map<Document>(x => x.Requires("Type").HasValue((int)TreeType.Document)).ToTable("L_DOCUMENTS");
modelBuilder.Entity<Product>()
.Map<Service>(x => x.Requires("ProductType").HasValue((int)ProductType.Service)).ToTable("L_SERVICES");
.Map<Ware>(x => x.Requires("ProductType").HasValue((int)ProductType.Ware)).ToTable("L_WARES");
modelBuilder.Entity<Document>()
.Map<Order>(x => x.Requires("ProductType").HasValue((int)DocumentType.Order)).ToTable("L_ORDERS");
.Map<Invoice>(x => x.Requires("ProductType").HasValue((int)DocumentType.Invoice)).ToTable("L_INVOICES");
}
}
In database it looks like this:
enter image description here
Two-level inheritance I can implement both through TPH, and through TPT, but multi-level inheritance, and even with several descriptors, I can not implement.
As an exit, I can use inheritance and combination, but the implementation is cumbersome and requires a lot of manual action to support in the future.
I tried to implement this architecture, but I did not succeed.
Does anyone know how I can do this?
I am having circular reference due to the EF code below. I have a Parent table with 2 childs and their grandchildren respectively. Is there any alternative to using Include, as I read something about Navigation property and it includes the parents in each of the child, causing the serialization having circular reference problem.
Error Message:
A circular reference was detected while serializing an object of type 'Product'.
This part is only to get retrieval and I don't need the parent reference back to each of the child. I debug inside and saw that inside each of the child, it has the parent reference back.
var query = db.Products.Include(c => c.ProductTriggers.Select(b => b.ProductTriggerItems))
.Include(d => d.ProductsExtra.Select(e => e.ProductAllotments.Select(m => m.ProductAllotmentDetails))).AsNoTracking();
return query.ToList();
Product Class
public partial class Product
{
public Product()
{
this.ProductExtras = new HashSet<ProductExtra>();
this.ProductTriggers = new HashSet<ProductTrigger>();
}
public int ProductID { get; set; }
public string ProductCode { get; set; }
public string ProductName { get; set; }
public virtual ICollection<ProductProduct> ProductExtras { get; set; }
public virtual ICollection<ProductTrigger> ProductTriggers { get; set; }
}
ProductExtra Class
public partial class ProductExtra
{
public ProductExtra()
{
this.ProductAllotments = new HashSet<ProductAllotment>();
}
public int ProductExtraID { get; set; }
public int ProductID { get; set; }
public virtual Product Product { get; set; }
public virtual ICollection<ProductAllotment> ProductAllotments { get; set; }
}
ProductAllotment Class
public partial class ProductAllotment
{
public ProductAllotment()
{
this.ProductAllotmentDetails = new HashSet<ProductAllotmentDetail>();
}
public int ProductAllotmentID { get; set; }
public int ProductExtraID { get; set; }
public virtual ProductExtra ProductExtra { get; set; }
public virtual ICollection<ProductAllotmentDetail> ProductAllotmentDetails { get; set; }
}
ProductTrigger Class
public partial class ProductTrigger
{
public ProductTrigger()
{
this.AddOnTriggerItems = new HashSet<ProductTriggerItem>();
}
public int ProductTriggerID { get; set; }
public int ProductID { get; set; }
public virtual Product Product { get; set; }
public virtual ICollection<ProductTriggerItem> ProductTriggerItems { get; set; }
}
ProductTriggerItem Class
public partial class ProductTriggerItem
{
public int ProductTriggerItemID { get; set; }
public int ProductTriggerID { get; set; }
public virtual ProductTrigger ProductTrigger { get; set; }
}
I´m using ef-core inheritance like this:
public abstract class Person
{
public int Id { get; set; }
public string Name { get; set; }
public PersonType PersonType { get; set; }
public int PersonTypeId { get; set; }
public double Height { get; set; }
[Timestamp]
public byte[] Timestamp { get; set; }
}
public class Daughter : Person
{
public double Weigth { get; set; }
public DateTime SomeDate { get; set; }
}
public abstract class Son : Person
{
public DateTime BirthDate { get; set; }
public DateTime GraduationDate { get; set; }
}
public class SingleSon : Son
{
}
public class SonWithDaughter : Son
{
public int Daughter { get; set; }
public Daughter Daughter { get; set; }
}
In DbContext:
public DbSet<PersonType> PersonTypes { get; set; }
public DbSet<Daughter> Daughters { get; set; }
public DbSet<SingleSon> SingleSons { get; set; }
public DbSet<SonWithDaughter> SonWithDaughters { get; set; }
When I update sql server database (dotnet ef database update) it throws a
System.InvalidOperationException, Sequence contains more than one
matching element
Any ideas about how to solve this?
UPDATE
ef migrations console output
This is issue #5894. It will be fixed in version 1.0.1. Until that's released, you can use the nightly feed.
Album, Article, and Photo are all derived classes of Content.
public class MyContext : DbContext
{
//What set should be here ???!
}
I wonder whether only adding public DbSet<Content> Contents { get; set; } is enough or need to represent all the entities like this?
public DbSet<Album> Albums { get; set; }
public DbSet<Article> Articles { get; set; }
public DbSet<Photo> Photos { get; set; }
public DbSet<Content> Contents { get; set; }
Thanks for helping.
I think you are looking for a sample of how to set up your model, this is an example.
you can create classes that are mapped to the same table.
public MyContext : DbContext
{
public MyContext() :
base("ConnectioString") // this is from the App.Config
{
}
public DbSet<Album> Albums { get; set; }
public DbSet<Article> Articles { get; set; }
public DbSet<Photo> Photos { get; set; }
public DbSet<Content> Contents { get; set; }
[Table("Content")]
public class Content
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ContentId { get; set; }
[Required]
public bool Field { get; set; }
}
[Table("Content")]
public class Album
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ContentId { get; set; }
[Required]
public bool Field { get; set; }
}
}