Stop EF Inheritance - c#

I have threeType MaliOp, LoanEBD, PrmEBD
public class MaliOp
{
public int Id { get; set; }
public int OldId { get; set; }
public byte MaliTable { get; set; }
public string Date { get; set; }
public short OpState { get; set; }
}
public class LoanEBD : MaliOp
{
public int? BId { get; set; }
public int? Loan { get; set; }
public int? PayerBimeGozar { get; set; }
[NotMapped]
public int OldId { get; set; }
}
public class PrmEBD : MaliOp
{
public int? PayerBimeGozar { get; set; }
public int? BId { get; set; }
[NotMapped]
public int OldId { get; set; }
}
the two Entity PrmEBD and LoanEBD Inherit from MaliOp. I want create DBContext in Entity Framework by by using this three types.
I have three Table in Database fro each one of them.
I don't want to use any EF Inhertance Strategy and add each one as Independent Types. but can't and EF Use either one of Inhertance strategy.
How can I do that?

create a IMaliOp Interface and let MaliOp implement it.
let the two classes implement the IMaliOp interface as well
Then use automapper (or something similar) to automatically transfer the information from the Entity object to your regular object.
This two classes would represent DTO (data transfer object). there are many strategies, out there for DTO-s
You should avoid having Classes inherit Entities, otherwise you applications classes will get too tightly coupled, and changes might prove them self to become too painful

In your context, override OnModelCreating;
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<PrmEBD>().ToTable("PrmEBDs");
modelBuilder.Entity<LoanEBD>().ToTable("LoanEBD");
modelBuilder.Entity<MaliOp>().ToTable("MaliOp");
}
This will create three separate tables in your database.
You will need to make sure that when you do a query over MaliOp, that you don't pull in instances from all three tables. You may want to go wit the approach of creating a common interface for all three, so that they don't actually inherit from each other, too

Related

Multilevel model classes in Entity Framewok Core 2.1

My database entity project has count about 30 columns, I would like to create clear EF Core model which many of them is grouped in several classes.
For example, overriding entity is Sensors and it has two elements (Int ID, ElectricalData electricalData), ElectricalData is a seperate class which has next 3 seperate classes and two bool and string objects.
A model constructed in this way in Add-Migration process returns feedback that sub-entities doesn't have a primary key, but they shouldn't contain PK, because only Sensors class should have a primary key.
How can I solve this problem? Does this idea is correct?
Code below:
public class SensorModel
{
[Key]
public int ID { get; set; }
public ElectricalDataModel ElectricalData { get; set; }
}
public class ElectricalDataModel
{
public TensionModel Tension { get; set; }
public CurrentModel Current { get; set; }
public string SecurityClass { get; set; }
public ResistanceModel Resistance { get; set; }
public bool ReversePolarizationSecurity { get; set; }
}
public class TensionModel
{
public double Minimum { get; set; }
public double Maximum { get; set; }
public string Current { get; set; }
}
//.......................................... and so on
What are you asking was called Complex Types, and the EF Core term is Owned Entity Types. By default they share the same table as the owner and are used to just logically separate (group) the related properties - exactly the goal you are describing.
The easiest way to identify a class as owned type in EF Core 2.1 is to mark it with OwnedAttribute:
[Owned]
public class ElectricalDataModel
{
// Properties..
}
[Owned]
public class TensionModel
{
// Properties..
}
//.......................................... and so on
Of course the same can be achieved via the OwnsOne fluent API, which also allows you to configure the column names and other attributes for the owned entity per owner.

EF7 Implement TPH + M2M

Is there a better way to accomplish this end-goal of having easily-queryable (and Include-able) cross-sections of a related many-to-many entity stored in the same table?
I started off without implementing TPH in the join table, but that makes consuming one type or another in queries more involved, afaict.
// table Related: [Id]
public class Related
{
public Guid Id { get; set; }
public List<RelatedOther> RelatedOthers { get; set; } = new List<RelatedOther>();
public List<RelatedOtherOne> RelatedOtherOnes { get; set; } = new List<RelatedOtherOne>();
public List<RelatedOtherTwo> RelatedOtherTwos { get; set; } = new List<RelatedOtherTwo>();
}
// table RelatedOther: [RelatedId, OtherId, Type]
public abstract class RelatedOther
{
public Guid RelatedId { get; set; }
public Guid OtherId { get; set; }
public Related Related { get; set; }
public Other Other { get; set; }
public abstract RelatedOtherType Type { get; }
}
public class RelatedOtherOne : RelatedOther
{
public override RelatedOtherType Type => RelatedOtherType.One;
// should be unnecessary, 'Other' should be correct type
public OtherOne OtherOne { get; set; }
}
public class RelatedOtherTwo : RelatedOther
{
public override RelatedOtherType Type => RelatedOtherType.Two;
// should be unnecessary, 'Other' should be correct type
public OtherTwo OtherTwo { get; set; }
}
public enum RelatedOtherType : int
{
One = 1,
Two = 2
}
// table Other: [Id, OneProp, TwoProp]
public abstract class Other
{
public Guid Id { get; set; }
public List<RelatedOther> RelatedOthers { get; set; } = new List<RelatedOther>();
}
public class OtherOne : Other
{
public string OneProp { get; set; }
}
public class OtherTwo : Other
{
public string TwoProp { get; set; }
}
TPH is mapped like this
M2M is mapped like this + discriminator in HasKey()
This gets even more complicated (if not impossible?) when the 'Related' entity evolves into a TPH strategy like the 'Other'.
I have no easy solution but as I stumbled across the same problem I thought I'll share what I have so far.
I found out that I usually need to load all or many types of the relations to the classes of a TPH structure.
So I use the base many-to-many class to load the related objects. Thus this class cannot be abstract:
public class Event2Location
{
[Required]
public Event Event { get; set; }
public int EventId { get; set; }
[Required]
public Location Location { get; set; }
public int LocationId { get; set; }
public byte EntityType { get; set; }
}
The derived class only adds some properties for easier access:
public class Event2Country : Event2Location
{
[NotMapped]
public Country Country
{
get { return base.Location as Country; }
set { base.Location = value; }
}
[NotMapped]
public int CountryId
{
get { return base.LocationId; }
set { base.LocationId = value; }
}
}
In the Event class I have:
public virtual ICollection<Event2Location> Event2Locations { get; set; }
[NotMapped]
public virtual ICollection<Event2Country> Event2Countries => Event2Locations?.OfType<Event2Country>().ToList();
// I should probably add some caching here if accessed more often
[NotMapped]
public virtual ICollection<Event2City> Event2Cities => Event2Locations?.OfType<Event2City>().ToList();
So when I load the joined tables I can use
.Include(e => e.Event2Locations).ThenInclude(j => j.Location)
And I can access the relations of a specific type as needed with the NotMapped Collections.
I still use the derived Event2... classes to add a new relationship.
As you see I have added a column EntityType to the many-to-many class which I use as TPH discriminator. With this column I can also declare which types of Relations/entities I want to load if I do not want to load all.
modelBuilder.Entity<Event2Location>()
.HasDiscriminator<byte>("EntityType")
.HasValue<Event2Location>(0)
.HasValue<Event2Country>(1)
This is surely far from perfect but I finally gave up on optimizing that. First EFCore has to become more mature. Second I want to see how I actually use these structures.
PS: Actually my Location TPH structure has parent-child-relationships within it. Here I did not create a TPH structure for the relation class (as you said - not possible or at least not reasonable). I added ParentType and ChildType. Thus I can determine which relations I actually want to load. Then I fetch the related Locations of the types I need manually on the client side from the result.

Multiple tables containing one entity in Entity Framework

I am working on a system that sells products. This system has products, with subclasses for every producttype.
public abstract class Product
{
public int ProductId { get; set; }
public string naam { get; set; }
public string barcode { get; set; }
}
public class Card :Product
{
[Display(Name = "Cardnumber")]
public int nummer { get; set; }
public Kaliber kaliber { get; set; }
}
Furthermore, i want to keep a history of all the products i sold with all the data that was correct at that moment.
public class Transaction
{
public int transactionId { get; set; }
public Member member { get; set; }
public virtual ICollection<Product> producten { get; set; }
public double totaalprijs { get; set; }
public DateTime tijdstip { get; set; }
public string kantoorMedewerker { get; set; }
}
The problem is, that entity now makes a FK in Product to Transaction. That's not what i want. I want a seperate table for each of them; a Products table and a SoldProducts table.
I already tried this in my productContext:
public DbSet<Product> producten { get; set; }
public DbSet<Product> uitgifte_producten { get; set; }
That's not possible, because EF doesn't allow multiple object sets per type .
This seems like something trivial, but i can't figure it out.
Making two classes, one Product and one Soldproduct, with both of having subclasses of the producttypes, seems rather ugly. I tried it, but VS2012 complains that it can't converty Product to SoldProduct.
What seems to be a good idea to do this in C#, .net 4.0 and EF?
Why not just link to products from your transaction class using a basic many-to-many relationship?
Using EF Fluent API, you can add a config class with the following:
public class TransactionConfig : EntityTypeConfiguration<Transaction>
{
public TransactionConfig ()
{
this.HasMany(t => t.Products)
.WithMany()
.Map(x =>
{
x.MapLeftKey("TransactionId");
x.MapRightKey("ProductId");
x.ToTable("TransactionProducts");
});
}
}
Then, override the OnModelCreating function of you DbContext with:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new TransactionConfig());
}
I assume you are using EF Code First.
When you have a collection of products in your Transactions table, EF will take this to be a typical one to many relationship.
I would add a TransactionDetail table to which I would copy all the details I need from Product:
public class TransactionDetail{
public int TransactionId { get; set; }
public int ProductId { get; set; }
public string naam { get; set; }
public string barcode { get; set; }
}
Update in response to comment:
Still assuming you are using code-first. In your scenario, you could use the TransactionDetail class above as a base class then have more derived classes in respect to the types of products. You will be able to capture all the required details per product and you will only have one more extra table in your db.
I don't know of any way to do something like this in EF.
If you really want to keep all the product data for each transaction, I'd suggest creating product copies for every transaction and then storing them in the DB and referencing them from the transaction. You might also think about creating a self-reference on product, which could then point to the "actual product" for "transaction products".
Another approach I can think of is storing the product history instead of creating a copy of the product, i.e. creating product copies on product change instead of on transaction creation. This way, when creating a transaction you always link to the current version of your product.

How to store two same entities in a database? Entity framework, c#

I have two entities with exactly the same properties:
public class Oil
{
public Guid Id { get; set; }
public string Title { get; set; }
public int Price { get; set; }
public int Ammount { get; set; }
}
public class Filter
{
public Guid Id { get; set; }
public string Title { get; set; }
public int Price { get; set; }
public int Ammount { get; set; }
}
Questions:
1) Can I somehow store them in one table? If so, than how?
2) Or should I implement inheritance? And what type then?
Edits:
In my case these two entities are just the same, they will not have any different properties in the future.
I implemented Table-per-Hierarchy approach, but there is another issue
(I have another type that has collections of oils and filters):
public class Warehouse
{
public Guid Id { get; set; }
public ICollection<Filter> Filters { get; set; }
public ICollection<Oil> Oils { get; set; }
}
So, when I create database, I get Warehouse_Id and Warehouse_Id1 fields in it. I don't want the Oil and Filter classes to have Warehouse property in them, how can I get just one field for Warehouse id in the db table?
If I include WarehouseId as a property in OilFilterBase class I will get 3 warehouse_id in the database table.
p.s. I also have DbSet<Oil> and DbSet<Filter> in my Context and don't have DbSet<OilFilterBase>.
It's hard to say what's best without knowing more about your requirements. What makes these two entities different? If they perform different functions and just happen to have the same properties, then it would probably be a good idea to store them in separate tables; that makes the most sense conceptually, and it would make things much easier if, say, you decided you wanted to add additional properties to one of them in the future.
On the other hand, if they're really the same at every level, it's also worth asking if you really need two different entity types to store them.
For the middle ground where the two classes serve related purposes but also differ in some ways, then yes, some form of inheritance might be a good approach -- either having one entity type derive from the other, or creating a new common base type and having both entities derive from that.
If you decide this is the best approach, then it looks like a good candidate for Table-per-Hierarchy mapping. You could restructure your code something like this:
public abstract class OilFilterBase
{
public Guid Id { get; set; }
public string Title { get; set; }
public int Price { get; set; }
public int Amount { get; set; }
}
public class Oil : OilFilterBase
{
}
public class Filter : OilFilterBase
{
}
...and then the Entity Framework will, by default, create a single table with an automatically-generated discriminator column, and store all instances of both entity types in that table.
If you decide that either of those entity types should have additional fields, then you could look at some of the other inheritance options, like Table-per-Type, that create separate but related tables for each entity type.
The first thing to do is decide how these classes fit together conceptually, and then figure out the best way to implement that in EF terms. If you can give more information about what these entities are and how they work, it'll be easier for people here to give good advice.
Response to Edits:
I think what's happening with the extra columns (Warehouse_Id and Warehouse_Id1) is this:
Because you're setting up the relationships for Oil and Filter separately, it's not comfortable assuming you want to use the base class's WarehouseId property as the foreign key -- what if you only wanted to set up that relationship for Oil and not Filter? It shouldn't be writing to the base class column in that case. So, it decides to create new properties instead.
Fortunately, you can use the [ForeignKey()] attribute (or the fluent API) to tell it what you really want, like this:
using System.ComponentModel.DataAnnotations.Schema;
public abstract class OilFilterBase
{
public Guid Id { get; set; }
public string Title { get; set; }
public int Price { get; set; }
public int Amount { get; set; }
public Guid WarehouseId { get; set; }
}
public class Oil : OilFilterBase
{
}
public class Filter : OilFilterBase
{
}
public class Warehouse
{
public Guid Id { get; set; }
[ForeignKey("WarehouseId")]
public virtual ICollection<Filter> Filters { get; set; }
[ForeignKey("WarehouseId")]
public virtual ICollection<Oil> Oils { get; set; }
}
Also, I think you'll need to include a DbSet<OilFilterBase> (in addition to DbSet<Oil> and DbSet<Filter>) in your context in order to get Table-per-Hierarchy inheritance to work -- try it and see.
Good luck!

Define simple data classes as abstract , interface or just classes?

Rather new to OOP..
I am gonna build a number of small applications that will support our main business.
These apps:
-Will need some common data classes
-The above classes may change in the future as far as properties are concerned (will add properties when ERP versions advance).
For example i have a class:
public class Lot
{
public string SSCC { get; set; }
public InventoryItem Item { get; set; }
public string DescriptionLocalLot { get; set; }
public string DescriptionEnglishLot { get; set; }
public DateTime ProductionDate { get; set; }
public string Shift { get; set; }
public string WorkOrder { get; set; }
public string ProductionLine { get; set; }
public string BarcodeEAN14 { get; set; }
public decimal Boxes { get; set; }
public decimal Units { get; set; }
public decimal Pieces { get; set; }
public DateTime LastUpdated { get; set; }
public string LastUser { get; set; }
public Warehouse LastWarehouse { get; set; }
public string ProductionLot { get; set; }
public string PalletSequence { get; set; }
}
The above class will be used by almost all applications (Windows forms or ASP pages). Ihave put this definition in a separate file called CommonClasses.
Should i define these classes as Abstract or Interfaces better? In most cases these classes will not include methods.
A class should describe all of an object's properties as well as methods that can act upon it. Not all are going to be used at once; but they are provided so that all the behavior is understood and state of an object can be tracked.
The class described in your code seems like a candidate for a concrete class. It provides a set of properties that are stored in memory and act in relation to one object. If you require additional functionality at a later point, you can extend the class to provide this.
If however, each instance of the class requires different implementation; then you should consider abstract class, or perhaps interface.
You should use concrete classes in your case if the change is common for all applications which are using these classes.

Categories

Resources