We are getting data for our application.
We have common set of data with common fields, PurchaseDate, Manufacturer, PurchaseAmount,
Then we have specific subclass (which contains specific vehicle info, Aircraft wingspan, or car miles/per gallon, or Boat floatation metrics.
Instead of having classes which are not required, how can we create a model with a specific data type?
public class VehicleInfo
{
public Datetime PurchaseDate { get; set; }
public string Manufacturer { get; set; }
public int PurchaseAmount { get; set; }
// specific data, not all these needed
public AircraftInfo AircraftInfo {get;set;}
public CarInfo Carinfo {get;set;}
public BoatInfo BoatInfo {get;set;}
}
I read Dependency injection is not ideal practice for DTOs? https://softwareengineering.stackexchange.com/a/83166/354368
You can choose from "is-a" (inheritance) or "has-a" (composition).
You already have what is common to all vehicles
public class VehicleInfo
{
public Datetime PurchaseDate { get; set; }
public string Manufacturer { get; set; }
public int PurchaseAmount { get; set; }
}
So you can use inheritance (and make VehicleInfo abstract)
public class AircraftInfo : VehicleInfo
{
...
}
or use composition
public class AircraftInfo
{
public VehicleInfo VehicleInfo { get; set; }
...
}
or mix composition and inheritance
public class PassengerAircraftInfo : AircraftInfo
{
public PassengerVehicleInfo PassengerVehicleInfo { get; set; }
...
}
If you have e.g. 5 out of 10 vehicles that shares a set of common properties in addition to common properties you already have, inheritance will require another abstract class that inherits from VehicleInfo. Composition will require a new property on each of the 5 vehicles.
What is best, depends on final result of your analysis for the project. Number of inheritance levels should be kept to a minimum in order to keep code complexity low.
Related
How would you migrate this Car Class to a database using the Entity Framework?
I have a Main car class (which inherits from a Car Interface Class) with one Generic property called Part
public class Car<Parts> : GenericCarInterface
{
public Parts Part { get; set; }
}
Then I have several enums representing different parts that can be passed into the Generic Parts property of the Car Class
public enum VokswagenParts
{
VWWheels,
VWLights,
VWEngine
}
public enum TyotaParts
{
ToyotaSpoiler,
ToyotaAirFilter,
ToyotaBrakes
}
public enum FiatParts
{
FiatExhaust,
FiatSuspension,
FiatCVOuter
}
I envisage setting up an ApplicationDbContext as follows but the EF does not know what to make of the Part property
public class ApplicationDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(#"ConnectionStringHere");
}
public DbSet<GenericCarInterface> Cars { get; set; }
}
Any Ideas on the ways that this can be accomplished using Entity Framework Core?
Looking at your enums, it looks like each part has a unique name. if you don't mind whether your parts are grouped or not, you could put all your parts together in single enum.
public enum Parts {
VWWheels,
VWLights,
VWEngine,
ToyotaSpoiler,
ToyotaAirFilter,
ToyotaBrakes,
FiatExhaust,
FiatSuspension,
FiatCVOuter
}
then in your Car class you can do this
public Parts Parts { get; set; }
EF should be able to handle the rest.
I think i may have figured out a solution.
If i can create a separate class in my repository to hold the enum number values and the enum type names:
public class Car
{
public Guid CarId { get; set; }
public Part Part { get; set; }
}
public class Part
{
public Guid CarId { get; set; }
public Guid PartId { get; set; }
public int Enum { get; set; }
public string EnumName { get; set; }
}
Then I can persist that standard class to the database then simply re-compile the code back to the original Car class format just before transferring between layers
I might create a separate enum for the part names just to keep it strongly typed but I like the idea of having the names persisted not just enum numbers
I'm using Entity Framework.
My Customer Entity is:
public partial class Customer
{
public virtual int ID { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual string CompanyName { get; set; }
}
And I have a BaseEntity class which is inherited by partial Customer class.
public class BaseEntity
{
public virtual int ID { get; set; }
}
public partial class Customer : BaseEntity
{
}
After that, I created a generic method as follows:
public static int GetId<T>(T entity) where T : BaseEntity
{
// id is zero after savechanges
var id = entity.ID;
return id;
}
My problem occurs when I want to get the id after SaveChanges() in the generic method, it's zero.
My test code is:
var db = new ContextDb();
db.Customers.Add(customer);
db.SaveChanges();
WriteLine($#"{customer.ID}"); // OK
WriteLine($#"{GetId(customer)}"); // Not OK --> ZERO
Thanks everyone for taking the time to try and help explain.
It is caused by the fact that, indeed, you have two ID fields: one (hidden) from BaseEntity (which has a value of zero) and one from Customer (which is not zero). Try to override the ID property or simply remove it from the Customer class declaration:
public partial class Customer
{
public override int ID { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual string CompanyName { get; set; }
}
You can also mark the ID property and BaseEntity class as abstract to force to override the ID property in inherited classes:
public abstract class BaseEntity
{
public abstract int ID { get; set; }
}
NOTE: Previously accepted answer is not good advice, while it satisfies the issue, for new developers it encourages them to think that it is normal to make all properties virtual or common practice to override every virtual member from the base class.
Because BaseEntity already defines ID, you SHOULD NOT be trying to re-implement ID in the inheriting class unless you specifically want to augment the original implementation.
In this case we are not offering any different implementation to the base and so should not be trying to override it.
Conversely, if you do want to force every inheriting class to implement a function or property in their own way, then mark it as abstract, not virtual, and follow this advice.
Putting all 3 class definitions in-line, I would recommend the following solution:
public class BaseEntity
{
public int ID { get; set; }
}
public partial class Customer : BaseEntity
{
}
public partial class Customer
{
// ID is provided from the base!
//public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string CompanyName { get; set; }
}
Using virtual properties becomes dangerous as a design choice because there is a gray area where auto-properties might or might not be implemented in the base or other inheriting classes. If all classes in the inheritance tree use auto-properties, then there is no issue, however when any traditional getter or setter that is not auto is overriden, if the override does not call back to the base implementation, then any references to the fields or placeholders that were implemented in the base will not have their values set.
which is pretty close to the situation that OP has raised.
Specifically with ORM tools like EF, I would caution making the ID property virtual or abstract at all.
The ID is too important to leave to chance.
If you are using virtual properties to support Lazy Loading, in EF you only need to make navigational properties virtual to support this, not every property on a class.
I'm looking for a class structure or design pattern to implement a base class that has a list of "base items", where several derived classes have the same list but that list is of derived "base items".
Here's a vastly stripped down example (ignore the accessibility of properties, they wouldn't actually all have public setters and default constructors):
public class BaseTransaction {
public List<BaseTransactionItem> Items { get; set; }
public void AddItem(string description, int quantity, decimal price)
{
// Add a new BaseTransactionItem to Items
}
}
public class BaseTransactionItem {
public string Description { get; set; }
public int Quantity { get; set; }
public decimal Price { get; set; }
}
public class OrderTransaction : BaseTransaction {
public List<OrderTransactionItem> Items { get; set; }
public int Deposit { get; set; }
public void SetDeposit(int depositAmount)
{
// Do some stuff to set the deposit.
}
}
public class OrderTransactionItem : BaseTransactionItem
{
public int QuantityFulfilled { get; set; }
}
public class RetailTransaction : BaseTransaction {
public List<RetailTransactionItem> Items { get; set; }
public List<Tender> Tenders { get; set; }
public void AddTender(Tender tender)
{
// Add a tender to the RetailTransaction
}
public decimal TotalTax
{
get { return Items.Sum(i => i.Tax); }
}
}
public class RetailTransactionItem : BaseTransactionItem
{
public decimal Tax { get; set; }
}
The way I need to work with these classes is that you start with a BaseTransaction and add some items to it, and then it can become either an OrderTransaction or a RetailTransaction. These both share most of their logic and properties with a BaseTransaction but have specific extra fields and methods, as well as the List<BaseTransactionItem> becoming a List<OrderTransactionItem> or a List<RetailTransactionItem> respectively.
Further more, after a BaseTransaction is "promoted" to a RetailTransaction, it may be "demoted" back to a BaseTransaction and then "promoted" to an OrderTransaction (but never from a RetailTransaction to an OrderTransaction in this case).
I've tried several approaches to this, with generics, the Decorator pattern (which doesn't seem appropriate), TypeConverters, and yet nothing seems to fit. The only possible solution I've thought of that works is having the RetailTransaction class have a constructor that takes a BaseTransaction and copying over all the properties and converting the list using .Cast<RetailTransactionItem> but this will make maintaining the derived classes pretty difficult.
If it wasn't for the list type needing to change this would be a simple case of using inheritance. I'm completely open to alternative approaches such as those favouring composition over inheritance but since the RetailTransaction and OrderTransaction classes truely are more specific versions of BaseTransaction, inheritance seems to fit - at least in my mind.
I'm trying to implement database structure in which there are common fields i put them in a separate abstract class but i want to know if 3 classes are inheriting from same abstract class and 2 have same property name so, by default entity framework will add a numeric followed by property name in database. Is there any way to implement this separately. I've studied complex types and searched over internet but couldn't find any flexible solution. I'm sharing my code, please guide me
public abstract class GenericImpression
{
[Key]
public int ImpressionId { get; set; }
public DateTimeOffset ReportingDate { get; set; }
}
public class Impression : GenericImpression
{
public string InventorySource { get; set; }
public string Media { get; set; }
}
public class Impression21 : GenericImpression
{
public string InventorySource { get; set; }
}
Now, EF will add one table with InventorySource1 and InventorySource Column.
Use OfType<>.
Example:
_context.GenericImpressions.ofType<Impression21>().ToList()
I'm trying to define a supply chain with Suppliers, Dealers and Retailers. This entities are bound by a Contract class that also defines the ProductLine and the Products they will work with.
For a given ProductLine, there will be a contract between a Supplier (the sole owner of that ProductLine) and a Dealer, and then another contract between this Dealer and a Retailer.
The problem is that there's also a contract between two dealers so I tried creating two interfaces (ISeller and IBuyer). Supplier implements ISeller, Retailer implements IBuyer and Dealer implements both interfaces:
public class Supplier : ISeller
{
public int Id { get; set; }
public virtual ICollection<Contract> Contracts { get; set; }
}
public class Dealer : ISeller, IBuyer
{
public int Id { get; set; }
public virtual ICollection<Contract> Contracts { get; set; }
}
public class Retailer : IBuyer
{
public int Id { get; set; }
public virtual ICollection<Contract> Contracts { get; set; }
}
The Contract then bounds a ISeller to a IBuyer, like this:
public class Contract
{
public int Id { get; set; }
public virtual ISeller Seller { get; set; }
public virtual IBuyer Buyer { get; set; }
}
Creating contracts between Supplier/Dealer or Dealer/Retailer works as intended, but I get a 'Multiplicity constraint violated' when trying to create a Dealer/Dealer contract.
It seems that the problem with this code is the interfaces. As Slauma said in the comments, the interface members of Contract class are not mapped at all since EF does not know, for example, which entities - Supplier, Dealer or both - map to Seller member.
From the other direction we have that each of the supply chain participants have multiple contracts. This results in Supplier_id, Dealer_id, Reseller_id columns in Contracts table. From EF perspective, Supplier and Dealer have nothing in common, neither do Retailer and Dealer.
What you need to do is to have entity inheritance. Dealer can be both seller and buyer though so you cannot have 2 separate classes as C# does not allow multiple inheritance. Define ContractParticipant base entity and have Supplier, Dealer and Retailer inherit from it. Then your data model would look something like:
public abstract class ContractParticipant
{
public int Id { get; set; }
[InverseProperty("Seller")]
public virtual ICollection<Contract> SellerContracts { get; set; }
[InverseProperty("Buyer")]
public virtual ICollection<Contract> BuyerContracts { get; set; }
}
public class Supplier : ContractParticipant
{
<...other properties here...>
}
public class Dealer : ContractParticipant
{
<...other properties here...>
}
public class Retailer : ContractParticipant
{
<...other properties here...>
}
public class Contract
{
public int Id { get; set; }
public virtual ContractParticipant Seller { get; set; }
public virtual ContractParticipant Buyer { get; set; }
}
This model should generate database structure that would support your scenario without any other configuration. However it would also allow contracts between any types of participants but If you try to map multiple inheritance in data model you would end up with something like this - consider if you want to complicate your data model to preserve these constraints.
Trying using this one :
public class Contract
{
public int Id { get; set; }
public virtual Seller Sellers { get; set; }
public virtual Buyer Buyers { get; set; }
}