I have a DLL with a base model using code first EF 4.3.
What i want is to extend certain models in that dll with additional fields.
for example in BaseModel.DLL
namespace BaseModel
{
public class Account
{
public Id { get;set;}
public string Name {get;set;}
}
}
in a referencing project i want to extend the Account model (and DB table):
public class Account : BaseModel.Account
{
public string SomeAdditionalInfo { get;set;}
}
I want to end up with a table Account with fields
Id
Name
SomeAdditionalInfo
This way i can keep reusing the BaseModel (and logic) in several similar projects.
I guess i can't use partial classes because we're speaking different DLL's.
Maybe inheritance? I tried several ways but i keep getting conflicts about having 2 models with the same name.
Any hints? tips? solutions?
You can use inheritance though Table per Hierarchy.
You can create base class AccountBase and child class Account:AccountBase:
public class AccountBase
{
public Id { get;set;}
public string Name {get;set;}
}
public class Account : AccountBase
{
public string SomeAdditionalInfo { get;set;}
}
It generates Table AccountBase that will contains columns Id, Name, SomeAdditionalInfo
There will be also column Discriminator that will contains instance of what class contains in this row.
Related
If I have a database with courses and course templates, and company course templates, what is the best way to store them in a SQL database? Course will probably have some other metadata about score, time-taken, and perhaps some other info.
Table Per Hierarchy
// Classes
public class CourseTemplate { }
public class CompanyCourseTemplate { }
public class Course { }
Table Per Type
public class CourseTemplate { }
public class CompanyCourseTemplate : CourseTemplate { }
public class Course : CompanyCourseTemplate { }
// Also for Course what if there are Course that belong to
// either CompanyCourseTemplate or else CourseTemplate
Hybrid Using Both - TPH
public class CourseTemplate { }
public class CompanyCourseTemplate : CourseTemplate { }
And - TPT
public class Course { }
It seems like the querying always gets messy when you need to differentiate the types within a table. As well, if you create a table per type the database gets cluttered with similar named tables as well. I am leaning towards the hybrid since it seems to be more natural with the types.
However, let's say we are storing a reference to the templates and we are using table per type what is the best way to manage this relationship?
In the exam table I could have two foreign keys to the template tables.
public class ExamTemplate { }
public class CompanyExamTempalte { }
public class Exam {
public Int32 ? ExamTemplateId { get;set; }
public Int32 ? CompanyExamTemplateId { get;set; }
The problem with this is that my code gets really ugly when I have to get an template from an exam template reference. I haven't found the best way to really take care of this problem. What is the best way to inherit from one of two templates. I am thinking that a hierarchy needs to be created where all exam instances must have a company exam template as well as a master template and the exam can hold references to both. The change would look like this.
public class Exam {
public Int32 CompanyExamTemplateId { get;set; }
public CompanyExamTemplate { get; set; }
public Int32 ExamTemplateId { get; set; }
public ExamTemplate { get; set; }
}
NOTE the nullables are gone since the hierarchy is always required.
Seems like you were initially leaning toward a one-to-many parent-child table structure something like this:
tblCourseTemplate:
CourseTemplateID
CourseTemplateName
CourseTemplateIsCompanyTemplate
CourseTemplateCompanyNameIfApplies
tblCourse:
CourseID
CourseTemplateID (i.e. parent record)
CourseName
CourseScore
CourseDateTaken
CourseTimeTaken
But then you said that a course could have more than one "parent" record so perhaps use an intermediate table to handle a many-to-many relationship:
tblCourseTemplate:
CourseTemplateID
CourseTemplateName
CourseTemplateIsCompanyTemplate
CourseTemplateCompanyNameIfApplies
tblCourseTemplateAndCourse:
CourseTemplateAndCourseID
CourseTemplateID
CourseID
tblCourse:
CourseID
CourseName
CourseScore
CourseDateTaken
CourseTimeTaken
I'm trying to make a class library that contains only the core logic of may app.
I've seen many tutorials that do this but they include the EF core inside that library. What I want to do is put only all the logic such, adding a category if it doesn't exist yet by passing a string.
Here 's what I want to do
Create a class library in separated project.
Add a class called SomeNameManager - [contains all the methods I want]
Create models to be modified by this manager but I don't want this to be the class directly used as my entity. I just want this to be the base class of my entity for customization. for example if I have to add a new propery, I'd just change the entity in my main app. not in the library.
The DbContext is in my main app only. Which means all of my classes and lists that used in my library will be just in the memory.
Here's what I got so far
// class library
public interface IBook{
// some properties here
ICollection<ICategory> Categories { get; set; }
// some more properties...
}
public interface ICategory{
// some properties here
ICollection<IBook> Books { get; set; }
// some more properties...
}
public class Book : IBook {
// implementations...
}
public class Category : ICategory {
// implementations
}
public class BookManager {
public void CreateBook(Book book) {
// some logic
// I'm not sure if I would pass Book or IBook
}
public void AddCategories(List<Category> categories) {
// some logic
// I'm not sure if I would pass Category or ICategory
}
}
// my main app
public class BookInfo {
// some props...
}
public class BookCategory {
// some props...
}
public class MyDB : DbContext{
public DbSet<BookInfo> BookInformations {get; set;}
public DbSet<BookCategory> BookCategories {get; set;}
}
The problems
The table name in my database is Book. I don't want to use fluent API just to rename this.
I have new column it both database called Discriminator. What is that? I do I remove that?
Categories isn't binding to Book.Categories. It's empty but it inserts to the database.
Additional Question
Am I doing this right?
Is it a bad idea? Please enlighten me. I'm not beginner but I haven't been in the real development team.
1 .The table name in my database is Book. I don't want to use fluent API just to rename this.
To give a class a different table name you can do this with the fluent API but since you don't want to do that you can use the [Table] attribute for this:
[Table("BookTableName")]
public class Book : IBook {
// implementations...
}
2. I have new column it both database called Discriminator. What is that? I do I remove that?
A discriminator column is used to identify which type each row represents.
See the docs
I am using EF 6.1.3 in all my POCO classes I have a common field that takes HTML value. I would like to add a common property for all these POCO classes that will strip HTML and hold clean string.
Current POCO class
public partial class Category
{
public string Name {get; set;}
public string Details {get; set;}
}
What I am looking to generate
public partial class Category
{
public string Name {get; set;}
public string Details {get; set;}
public string CleanDetails
{
get{ return StripHtml(this.Details ); }
}
}
And I should not lose this custom property every time I update the Entity model
public string CleanDetails
{
get{ return StripHtml(this.Details ); }
}
Tried working on Mode.Context.tt to make the following change, but was not useful
public string EntityClassOpening(EntityType entity)
{
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1}partial class {2}{3}",
Accessibility.ForType(entity),
_code.SpaceAfter(_code.AbstractOption(entity)),
_code.Escape(entity),
_code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType) ?? "BaseEntity" ));
}
I see there is a way to create partial classes for all those where I need this custom property. But I need this in about 40 classes and there could be more classes coming in future, I want it to be like more of automated approach, then manually creating 40 partial classes.
It is possible to implement inheritance in EF6. You could create a base class with all your shared methods and properties, then if you made all your entity types inherit from it (see link) you would have the behaviour you are after. The only problem would be that if you deleted a table from your model and then re-added it from the database you would have to make it inherit from base class again.
I generated another folder in my database project for my self and added theses properties in another partial class .add CSharp file to that folder and insert file name same with your class ( Category) and change namespace too
public partial class Category
{
public string CleanDetails
{
get{ return StripHtml(this.Details ); }
}
}
I'm using EF5 to produce a model from an existing DB structure. I map Insert/Update/Delete Stored Procedures to the entities. This is working fine.
What I would like to do next is pass a UserId to these SPs as a parameter but not have the UserId as a column within the underlying table (the SPs will utilize this parameter). I have lots of entities. Is it possible to somehow add a property that will always be added back in even after updating the model from the DB?
Many Thanks
If you are using EDMX to generate the Entity Framework object model, your classes are partial and you can add properties to the partial classes of your entities which will survive database regeneration.
If you have a ParticularEntity table in the DB and referenced in the EDMX, you may add a partial class file ParticularEntity.Augments.cs (the name is for your reference, and you can have multiples as normal with partial classes) to your project and within it
public partial class ParticularEntity
{
public string UserId { get; set; }
public void DoSomething(string userId)
{
someFunctionThatYouWantToNotBeAnExtension();
}
}
Alternatively, you could write a set of extension methods which your maps utilize. I don't think that's as clean as extending the EF classes with partials, though.
Entity created by EF are partial class so you can extend that class with your custom properties
YourEntity.cs //created by EF
public partial class YourEntity
{
public string Name { get; set; }
...
}
YourEntityExtended.cs // created by you
public partial class YourEntity
{
public int Id { get; set; }
}
I currently have the following in one solution:
Core Project (data access, biz logic, petapoco for data access, the plumbing, etc)
Models Project (just models and petapoco decorations for just attributes)
Web Project (MVC project for presentation
I want to have my Models and Core seperate, but I can't have PetaPoco.cs in both places. How would I seperate it and still be able to decorate the POCOs in my Models project with PetaPoco attributes?
I don't want the Models project to have a dependency on the Core project.
I did create this seperate class to be only in the Models project so I could decorate the POCOs, but the attributes are not being picked up properly by the Core PetaPoco project. It relies on PocoData too much.
Suggestions?
// Poco's marked [Explicit] require all column properties to be marked
[AttributeUsage(AttributeTargets.Class)]
public class ExplicitColumnsAttribute : Attribute
{
}
// For non-explicit pocos, causes a property to be ignored
[AttributeUsage(AttributeTargets.Property)]
public class IgnoreAttribute : Attribute
{
}
// For explicit pocos, marks property as a column and optionally supplies column name
[AttributeUsage(AttributeTargets.Property)]
public class ColumnAttribute : Attribute
{
public ColumnAttribute() { }
public ColumnAttribute(string name) { Name = name; }
public string Name { get; set; }
}
// For explicit pocos, marks property as a result column and optionally supplies column name
[AttributeUsage(AttributeTargets.Property)]
public class ResultColumnAttribute : ColumnAttribute
{
public ResultColumnAttribute() { }
public ResultColumnAttribute(string name) : base(name) { }
}
// Specify the table name of a poco
[AttributeUsage(AttributeTargets.Class)]
public class TableNameAttribute : Attribute
{
public TableNameAttribute(string tableName)
{
Value = tableName;
}
public string Value { get; private set; }
}
// Specific the primary key of a poco class (and optional sequence name for Oracle)
[AttributeUsage(AttributeTargets.Class)]
public class PrimaryKeyAttribute : Attribute
{
public PrimaryKeyAttribute(string primaryKey)
{
Value = primaryKey;
autoIncrement = true;
}
public string Value { get; private set; }
public string sequenceName { get; set; }
public bool autoIncrement { get; set; }
}
[AttributeUsage(AttributeTargets.Property)]
public class AutoJoinAttribute : Attribute
{
public AutoJoinAttribute() { }
}
I think one obvious solution, though, I'm not sure it's that much better, is to move PetaPoco to its own project and then reference that in both your Core and Models projects. Your models still have an external dependency, though, just not the whole Core assembly.
One other alternative would be to have your decorated models in your Core project for internal use, and then have a set of undecorated classes in your Models assembly. You could use an auto-mapping component to map between the two easily. So basically you would use PetaPoco to fetch data into your internal model, and then map that over to your 'external' model which is just bare classes with no dependencies.
Of course, that sounds like a lot of extra work. I guess it all hinges on how critical it is that your Model assembly have no other dependencies.