What is the best aproach to develop a TPH based entity with Entity Framework, for example, if I have common fields in an Ads website, and specific ones:
public class Ad
{
// Primary properties
public int Id { get; set; }
public string Title { get; set; }
public string TitleStandard { get; set; }
public string Version { get; set; }
public string VersionStandard { get; set; }
public int Year { get; set; }
public decimal Price { get; set; }
// Navigation properties
public Color Color { get; set; }
public Member Member { get; set; }
public Category Category { get; set; }
public IList<Feature> Features { get; set; }
public IList<Picture> Pictures { get; set; }
public IList<Operation> Operations { get; set; }
}
public class AdCar : Ad
{
public int Kms { get; set; }
public Model Model { get; set; }
public Fuel Fuel { get; set; }
}
public class AdBoat : Ad
{
public int Hours { get; set; }
public string Model { get; set; }
}
Do I have to build specific operations for every subclass:
CreateAdCar()
CreateAdBoat()
Or can I have something like:
CreateAdCommon() and CreateAdCar()
How can I split the two classes so I don't have to repeat all the code for the Car Ad class and Boat Ad class?
Related
I have these tables: Sales, product, stock and salesProduct. I'm using a database first approach, they were created using EF scaffold. Sales table looks like this:
public partial class Sales
{
public Sales()
{
SalesProduct = new HashSet<SalesProduct>();
}
public int Id { get; set; }
public DateTime? CreationDate { get; set; }
public bool IndActive { get; set; }
public virtual ICollection<SalesProduct> SalesProduct { get; set; }
}
}
I need the post method on sales creation to create a SalesProduct object and add it to the database. I also need it to update the stock of that specific product.
Here are the other tables:
public partial class SalesProduct
{
public int Id { get; set; }
public int SaleId { get; set; }
public int ProductId { get; set; }
public decimal? Value { get; set; }
public bool IndActive { get; set; }
public virtual Produto IdProductNavigation { get; set; } = null!;
public virtual Vendum IdSalesNavigation { get; set; } = null!;
}
}
public partial class Stock
{
public int Id { get; set; }
public int IdProduct { get; set; }
public int? Quantitu { get; set; }
public bool IndActive { get; set; }
public virtual Product IdProductNavigation { get; set; } = null!;
}
}
How can i do that? I'm confused on how to deal with entity relationships in http methods!
I'm using Entity Framework, I don't want to configure any relationship between my entities, just want them for code reusability, but I get this error:
Unable to determine the relationship represented by navigation 'StallType.CashCollateral' of type 'CashCollateral'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'
My code:
public class Stall
{
public Guid Id { get; set; }
public StallDetails StallDetails { get; set; }
}
public class StallDetails
{
public string Location { get; set; }
public StallPeculiarities StallPeculiarities { get; set; }
}
public class StallPeculiarities
{
public string Name { get; set; }
public StallType StallType { get; set; }
}
public class StallType
{
public string Type { get; set; }
public double Value { get; set; }
public double TenorInMonths { get; set; }
public double RentalRate { get; set; }
public SecurityDeposit SecurityDeposit { get; set; }
public CashCollateral CashCollateral { get; set; }
}
public class SecurityDeposit
{
public double Staff { get; set; }
public double Customer { get; set; }
}
public class CashCollateral
{
public double Staff { get; set; }
public double Customer { get; set; }
}
I have got the following three tables (just an example)
public class User
{
public int id { get; set; }
public string name { get; set; }
public List<Code> Codes { get; set; }
}
public class Device
{
public int id { get; set; }
public string name { get; set; }
public List<Code> Codes { get; set; }
}
public class Code
{
public int id { get; set; }
public int entity_id { get; set; }
public string entity_type { get; set; }
public string code { get; set; }
}
Now a code can either belong to a User or a Device, which will be determined by the value of entity_type (i.e. 'user' or 'device'). How can this be achieved in Entity Framework ?
You could change your Code class to
public class Code
{
public int id { get; set; }
public User user { get; set; }
public Device device { get; set; }
public string code { get; set; }
}
This way one of those properties can be null.
Hope it helps.
The drawback is that you could have a code that have a user an a device
I am trying to set up a relationship where a Car can have multiple Testruns, as well as an optionally selected "active testrun".
public class Car
{
public int ID { get; set; }
public virtual TestRun ActiveTestRun { get; set; }
public virtual ICollection<TestRun> TestRuns { get; set; }
}
public class TestRun
{
public int ID { get; set; }
public double TopSpeed { get; set; }
public virtual Car ActiveCar { get; set; }
public virtual Car Car { get; set; }
}
I have been trying to use InverseProperties with or without ForeignKey-attributes but to no luck. What is the correct way to setup this kind of relation? TIA!
Ps. I think I tried mostly all of the combinations from this tutorial without getting it to work :(
http://www.entityframeworktutorial.net/code-first/inverseproperty-dataannotations-attribute-in-code-first.aspx
EDIT: The resulting DB-schema I would want is something like:
tbl_Cars:
ID, ActiveTestRunID[Nullable]
tbl_TestRuns:
ID, TopSpeed, CarID
This achieved the result that I wanted:
public class Car
{
public int ID { get; set; }
public int? ActiveTestRunID { get; set; }
public virtual TestRun ActiveTestRun { get; set; }
[InverseProperty("Car")]
public virtual ICollection<TestRun> TestRuns { get; set; }
}
public class TestRun
{
public int ID { get; set; }
public double TopSpeed { get; set; }
public int CarID { get; set; }
public virtual Car Car { get; set; }
}
I am trying to understand how to create a ViewModel that contains properties from a class in my domain model as well as properties from a parent class.
I want to have a ViewModel that contains all of the LoadSession properties and the TradingPartner Description, but I'm not sure how to map this all up in the ViewModel. Any help or advice would be greatly appreciated.
This is my main class I'm accessing named LoadSession:
public partial class LoadSession
{
public LoadSession()
{
this.AcceptedTransactions = new HashSet<AcceptedTransaction>();
this.RejectedTransactions = new HashSet<RejectedTransaction>();
}
public int LoadSessionId { get; set; }
public int Import { get; set; }
public string FilePath { get; set; }
public string TradingPartnerBatchId { get; set; }
public System.DateTime Started { get; set; }
public int RecordsOnFile { get; set; }
public int RecordsAfterGroupFilter { get; set; }
public int RecordsAccepted { get; set; }
public int RecordsRejected { get; set; }
public System.DateTime Completed { get; set; }
public bool Success { get; set; }
public Nullable<int> Extract { get; set; }
public virtual ICollection<AcceptedTransaction> AcceptedTransactions { get; set; }
public virtual Extract Extract1 { get; set; }
public virtual Import Import1 { get; set; }
public virtual ICollection<RejectedTransaction> RejectedTransactions { get; set; }
}
The Import property is a foreign key for this Import class (Import = ImportId):
public partial class Import
{
public Import()
{
this.GroupPlans = new HashSet<GroupPlan>();
this.ImportGroups = new HashSet<ImportGroup>();
this.MatchingGroups = new HashSet<MatchingGroup>();
this.LoadSessions = new HashSet<LoadSession>();
}
public int ImportId { get; set; }
public string Description { get; set; }
public int Format { get; set; }
public int Interface { get; set; }
public virtual Interface Interface1 { get; set; }
public virtual Format Format1 { get; set; }
public virtual ICollection<GroupPlan> GroupPlans { get; set; }
public virtual ICollection<ImportGroup> ImportGroups { get; set; }
public virtual ICollection<MatchingGroup> MatchingGroups { get; set; }
public virtual ICollection<LoadSession> LoadSessions { get; set; }
}
The Interface property is a foreign key for this Interface class (Interface = InterfaceId):
public partial class Interface
{
public Interface()
{
this.Extracts1 = new HashSet<Extracts1>();
this.Imports = new HashSet<Import>();
}
public int InterfaceId { get; set; }
public string Description { get; set; }
public int TradingPartner { get; set; }
public virtual ICollection<Extracts1> Extracts1 { get; set; }
public virtual ICollection<Import> Imports { get; set; }
public virtual TradingPartner TradingPartner1 { get; set; }
}
And the TradingPartner property is a foreign key for this TradingPartner class (TradingPartner = TradingPartnerId):
public partial class TradingPartner
{
public TradingPartner()
{
this.Interfaces = new HashSet<Interface>();
}
public int TradingPartnerId { get; set; }
public string Description { get; set; }
public virtual ICollection<Interface> Interfaces { get; set; }
}
Well, those are all your domain objects right...
Create a repository that takes your Domain object and transforms then to into a view model with the properties you need...
I am not sure what it is your view needs, but from your statements you state that you want properties of Load session + TradingPartner.Description So create something like this...
public class LoadSessionTradingPrtNrVM
{
public LoadSession()
{
this.AcceptedTransactions = new HashSet<AcceptedTransaction>();
this.RejectedTransactions = new HashSet<RejectedTransaction>();
}
public int LoadSessionId { get; set; }
public int Import { get; set; }
public string FilePath { get; set; }
public string TradingPartnerBatchId { get; set; }
public System.DateTime Started { get; set; }
public int RecordsOnFile { get; set; }
public int RecordsAfterGroupFilter { get; set; }
public int RecordsAccepted { get; set; }
public int RecordsRejected { get; set; }
public System.DateTime Completed { get; set; }
public bool Success { get; set; }
public Nullable<int> Extract { get; set; }
public string Description { get; set; }
public virtual ICollection<AcceptedTransaction> AcceptedTransactions { get; set; }
public virtual Extract Extract1 { get; set; }
public virtual Import Import1 { get; set; }
public virtual ICollection<RejectedTransaction> RejectedTransactions { get; set; }
}
To get from Domain models to ViewModels you would use a repository, or some other pattern that takes what you get from your database and transforms it into what you need for your views.
This is kind of raw, but the theory should hold...
public class DataRepository {
LoadSessionTradingPrtNrVM TransformToVM(LoadSession inputA, TradingPartner inputB){
LoadSessionTradingPrtNrVM newOBJ = new LoadSessioNTradingPrtNrVM();
newOBJ.LoadSessionId = ipnutA.LoadSessionID;
newOBJ.Import = inputA.Import
//Here is the property from your Transform object
newOBJ.Description = inputB.Description
//... Continue to transform one object into the other...
//You could add as many members from as many different objects as you want into
//Your view model following that pattern.
}
}
I didn't have a chance to run this through a C# compiler, but you should get the general idea. I am sure there is a more elegant pattern that can accomplish the same thing. But this is a decent solution off the top of my head.
Another option is to include the domain model objects as properties in the view model. For example:
// View model.
public class UserViewModel
{
public AddressModel Address; // Assuming "AddressModel" is a doman model.
public string FirstName;
public string LastName;
}
And in the view you can access the properties as:
#Model.Address.AddressLine1
#Model.Address.City
// etc...
The Html helpers handle this just fine, but if you are manually naming inputs in your view don't forget to adjust those names to match.