I am designing the architecture of a .Net project in C#.
I will use EF.
I want to set a MVC pattern architecture.
Although I will start with a first Model implementation, I might have to use other Models that will be QUITE similar to the original one.
I obviously want to implement a single Business layer that would ideally work with both Model implementations.
So I suppose I will have to intensively rely on interfaces at some point.
USUALLY, I build my entities and context this way:
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
... other properties
}
public class Bar
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Foo Fooo { get; set; }
... other properties
}
...
public class MyContext : DbContext
{
...
}
Now, in my case, I will have let's say 2 different models.
On top of the precedently written Foo and Bar classes, I will have:
public class Foo2
{
public int Id { get; set; }
public string Name { get; set; }
... other properties
}
public class Bar2
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Foo Fooo { get; set; }
... other properties
}
...
public class MyContext2 : DbContext
{
...
}
Now how to set a single business layer that can deal either with MyContext or MyContext2 ?
I suppose the the fist step is to create interfaces for For Foo / Foo2 and Bar / Bar2:
public interface IFoo
{
int Id { get; set; }
string Name { get; set; }
}
public interface IBar
{
int Id { get; set; }
string Name { get; set; }
IFoo Fooo { get; set; }
}
Then what????
Related
Let's say you have a Car Park, each car park hold x amount of Cars and each car can have different properties. Like this:
public class CarPark
{
public int Id { get; set; }
public ICollection<ICar> Cars { get; set; }
}
public interface ICar
{
string Model { get; set; }
}
public class Volvo : ICar
{
public string Model { get; set; }
public string Color { get; set; }
}
public class Bmw : ICar
{
public string Model { get; set; }
public int Wheels { get; set; }
}
How do you deal with that kind of scenario when the models are different?
Assuming you mean how you have to deal with EF messing up the mapping of your models due to the Interface: you can manually configure the translation of your models in the OnModelCreation method of your DbContext.
Look here for more information: https://learn.microsoft.com/en-us/ef/core/modeling/
I found a solution, instead of using a interface you create an abstract class, i adjusted the code above to show how it's done:
public class CarPark
{
public int Id { get; set; }
public virtual ICollection<Car> Cars { get; set; }
}
public abstract class Car
{
public int Id { get; set; }
public string Model { get; set; }
}
[Table("Volvo")]
public class Volvo : Car
{
public string Color { get; set; }
}
[Table("Bmw")]
public class Bmw : Car
{
public int Wheels { get; set; }
}
Because of the table annotation each car will end up in a separate table, this strategy is called TPT - Table Per Type, if the attribute is removed all cars will end up in the same table, that strategy is called TPH - Table Per Hierarchy.
The example is pretty bad but imagine each car is a payment provider with unique settings or something similar.
More info:
https://www.entityframeworktutorial.net/code-first/inheritance-strategy-in-code-first.aspx
I have 2 models which have exactly same fields, but I chose to make different models for them because I needed two different tables, one for each.
Earlier everything was working fine when I had two different tables for each model, but then I started using abstract base class because the code inside both the models were same.
Now I have a single table comprised of all the data that I save.
How can I create different tables for those two models.
public abstract class baseGrammar
{
[Key]
public int Id { get; set; }
[Required]
public string question { get; set; }
[Required]
public string ans { get; set; }
public string ruleId { get; set; }
public string ruleApplicable { get; set; }
[ForeignKey("ruleId")]
public virtual ruleTable RuleTable { get; set; }
}
The one shown above is my abstract base class.
public class article : baseGrammar
{
}
public class adjective : baseGrammar
{
}
Just if someone intrested in ruleTable model.
public class ruleTable
{
[Key]
public string ruleId { get; set; }
public string topic { get; set; }
public string rule { get; set; }
public string example { get; set; }
public virtual ICollection<baseGrammar> BaseGrammar { get; set; }
}
Am also adding context class so as to provide better description
public class english : DbContext
{
public english() : base("name=localServerEng")
{
Database.SetInitializer<DbContext>(null);
Database.SetInitializer<english>(new UniDBInitializer<english>());
}
public virtual DbSet<adjective> adjectiveDb { get; set; }
public virtual DbSet<adverb> adverbDb { get; set; }
public virtual DbSet<alternativeVerb> alternativeVerbDb { get; set; }
public virtual DbSet<antonyms> antonymsDb { get; set; }
public virtual DbSet<article> articleDb { get; set; }
private class UniDBInitializer<T> : DropCreateDatabaseIfModelChanges<english>
{
}
public System.Data.Entity.DbSet<StructureSSC.Areas.AreaEnglish.Models.baseGrammar> baseGrammars { get; set; }
}
Screenshot of SQL Server showing 1 table comprising of all columns instead of different tables
This set up will give you 2 tables: (1) adjectives (2) articles
The context should be like this:
public class SomeContext : DbContext
{
public SomeContext()
: base("name=SomeContext")
{
}
public virtual DbSet<article> Articles { get; set; }
public virtual DbSet<adjective> Adjectives { get; set; }
}
public abstract class baseGrammar
{
//... common properties/columns
}
public class article : baseGrammar
{
}
public class adjective : baseGrammar
{
}
Please note the naming convention. In .NET class names and property names should follow Pascal Notation. Therefore, they should be:
BaseGrammar
Article
Adjective
RuleApplicable // other properties should follow same convention
This is my first time here so sorry if I did not put the doubt by default. In my project I have two models class doubts and a class of works, I want to create a classification for both using a superclass, like the design pattern strategy. But I have a problem, the project state is advanced and I have used the doubt and works classes many times. Already tried in many ways, but either the error in the update-database or the error in what I had done before.
Does anyone know one way that I can implement a generic class classification for the doubts and works classes without many changes of what I had already done?
My code is below
public abstract class Classificable
{
[Key]
public int id { get; set; }
public virtual Classification classication { get; set; }
}
public class Doubt : Classificable
{
public int doubtID { get; set; }
public string question { get; set; }
public string content { get; set; }
public virtual Student student { get; set; }
public virtual Course course { get; set; }
public virtual Work work { get; set; }
public virtual ICollection<Answer> answers { get; set; }
}
public class Work : Classificable
{
public int workID { get; set; }
public string name { get; set; }
public string nameWork { get; set; }
public string filePath { get; set; }
public virtual Student student { get; set; }
public virtual Course course { get; set; }
public virtual ICollection<Doubt> doubts { get; set; }
}
public class DB_DIS : DbContext
{
public DB_DIS()
: base("name=DB_DIS")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Doubt>().ToTable("Doubts");
modelBuilder.Entity<Work>().ToTable("Works");
}
public virtual DbSet<Doubt> Doubts { get; set; }
public virtual DbSet<Work> Works { get; set; }
}`
What is the property or method in Classificable that you are trying to apply to Doubt and Work?
Have you written your data structure in such a way that is contains an id field AND workID feild?
In my experience, if you are trying to share properties between EF Classes you are better off sharing common fields. I've used it in the past for base classes of AuditableBase as follows:
public class AuditableBase
{
public string UpdateUserId { get; set; }
public DateTime UpdateDate { get; set; }
}
Then all my classes that I want to "Audit" will have a UpdateUserId and UpdateDate, and I can do some pre-save processing to set those based on the type of AuditableBase.
My program is starting to get pretty big. and i have found that its starting to do the same thing in multiple area's.
Im trying to figure out how i can make it more efficient.
So i have an object that looks like this
public class TreeViewNode
{
public TreeViewNode()
{
Children = new ObservableCollection<TreeViewNode>();
}
public String Name { get; set; }
public string Description { get; set; }
public ObservableCollection<TreeViewNode> Children { get; set; }
}
i also have another object that looks like this;
public class ComputerObject
{
public String Name { get; set; }
public Int32 UUID { get; set; }
public DateTime Created { get; set; }
public ObservableCollection<Object> Children { get; set; }
}
Both these items need to have some of the same properties..
at the moment they both have the Children Property and the Name Property. but they both need to have some other common properties added to them.
so i have tried something like this.
public class BaseObject
{
public String Name { get; set; }
public ObservableCollection<Object> Children { get; set; }
public string Description { get; set; }
public BaseObject()
{
Children = new ObservableCollection<object>();
}
}
public class ComputerObject: BaseObject
{
public Int32 UUID { get; set; }
public DateTime Created { get; set; }
}
public class TreeViewNode: BaseObject
{
public String IconPath { get; set; }
}
Now this is just a cut down version of what i am implementing, i have alot of objects that share the same properties. and some that dont and mix and match. and i cannot figure out the best implimentation for this.
My Objects are becoming very cluttered, and when i rename a property i find that i have to rename it in several area's and this isnt the way its ment to be.
can someone please advise how i would implement multiple objects that share the same property names?
In my opinion you should not let classes inherit from one baseclass when these childclasses are not related to each other (like #Sriram Sakthivel asked Animal < Dog,Cat) just to share the same properties.
You should determine which classes are related (cat, dog are animals; car, motorcycle are vehicles) and then create baseclasses based on these "groupings".
I would look into decorator pattern. In short, you dont share common properties via inheritance. You make classes that contain common properties, and use these classes as properties in your end classes.
EDIT: Example is actually just a standard composition, it should work nevertheless
E.G.
public class Decorator1
{
public String Name { get; set; }
public ObservableCollection<Object> Children { get; set; }
public string Description { get; set; }
}
public class Decorator2
{
public long Id { get; set; }
}
public class ClassA
{
public Decorator1 TreeNodeImpl;
}
public class ClassB
{
public Decorator1 TreeNodeImpl;
public Decorator2 LongIdImpl;
}
I have four MVC model layer domain classes.
namespace MvcMobile.Models.BusinessObject
{
public class Speaker
{
public int SpeakerID { get; set; }
public string SpeakerName { get; set; }
}
public class Tag
{
public int TagID { get; set; }
public string TagName { get; set; }
}
public class Seminar
{
public string Seminar_Code { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Room { get; set; }
}
public class Seminar_Detail
{
public string Seminar_Code { get; set; }
public int SpeakerID { get; set; }
public int TagID { get; set; }
public string DateAndTime { get; set; }
}
}
I would like to make CRUD operation by using these classes. So I create two VeiwModel Classes.
namespace MvcMobile.ViewModel
{
public class Seminar_Root_ViewModel
{
public Seminar_Subsidiary_ViewModel Seminars { get; set; }
public List<Speaker> Speakers { get; set; }
public List<Tag> Tags { get; set; }
}
public class Seminar_Subsidiary_ViewModel
{
public Seminar Seminar { get; set; }
public List<Seminar_Detail> Seminar_Detail { get; set; }
}
}
For Controller layer, I consider that I will use Seminar_Root_ViewModel to make the whole CRUD operation processes.
What I would like to ask is that Is this proper way or correct way?
If you have more elegant way to make model layer and ViewModel layer, Please let me get suggestion.
Every suggestion will be appreciated.
[updated]
Let's assume that I make master-Detail form design.
Speaker and Tag are just look-up tables for dropdownlist or some controls like that.
Seminar is Master Data and Seminar_Detail will be Item Grid Data.
So As for this scenario, all of this classes are needed for this program.
Please let me know if my thinking is wrong.
The only thing I can see is if you are not going to re-use your Seminar_Subsidiary_ViewModel view model you could skip it.
If you are going to need those two properties Seminar and Seminar_Detail on another view or ajax call, it's perfectly fine to have that kind of separation.
Personally I'm not a huge fan of _ on class name, but that have nothing to do with the question.