asp.net class library that talks to ef and customizable - c#

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

Related

Should I use Table Per Type or Table Per Hierarchy?

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

How to define collections in a common interface to fit EntityFrameworks auto generated collections?

I'm creating a multi platform application (.NET 4.5/WPF, Windows Phone 8, SilverLight 5) using the MVVM pattern. My ViewModel project is a PCL (portable class library) shared/used by all platform specific Views. In my Windows application I want to access the database directly via Entity Framework 6.
I've two projects representing the data layer:
Data.Common: Includes entity/repository/unitofwork interfaces. They are used in my ViewModels.
Data.EF: Includes EntityFramework "stuff" (edmx file = auto generated DbContext and entity classes)
I will show my problem with my IUser interface:
// Data.Common.IUser
public interface IUser : IEntity
{
// Primitives representing table columns.
// They will be implemented fine by EF's auto generated classes.
int ID { get; set;}
string UserName { get; set; }
// Collections representing table relations.
// They are my problem because EF's generated classes don't fit to this.
ICollection<IUserApplication> UserApplications { get; set; }
}
To implement my interface I created a partial class for each EF auto generated entity class in Data.EF project:
// Data.EF.User, my file
public partial class User : IUser
{
// fields are implemented in other part
}
// Data.EF.User, file created by EntityFramework
public partial class User
{
public User()
{
this.UserApplications = new HashSet<UserApplication>();
}
public int ID { get; set; } // fine, this implements IUser.ID
public string UserName { get; set; } // fine, this implements IUser.UserName
// And here's the other part of my problem:
// This collection is of type ICollection<UserApplication> but UserApplication is not known in my ViewModel, only IUserApplication.
public virtual ICollection<UserApplication> UserApplications { get; set; }
}
How should the collections (like ICollection<IUserApplication>) representing the data table relations in my interfaces look like? It's not possible to simply cast a Collection<IUserApplication> to a Collection<UserApplication> so can this be achieved in any other way?

EntityFramework extend base model in different DLL

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.

How would I use a seperate Models only project with PetaPoco?

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.

c# DAL class and business layer class

HI,
can you tell me if this is possible.
public class Person
{
public string Name { get; set; }
public int ID { get; set; }
}
Populate a class call say person which is in an assembly called Entities like this with the population of the code being done in a different assembly called DataAccessLayer (so person and the place where it is populated are not in the same assembly)
//the below code would be reading from a datareader etc but have just done this to make it //easy to explain.
Person p=new Person();
p.Name="tom";
p.id = 10;
The person class is now to be made accessible to another system to allow them to be able to access person. What i would like is to prevent the other system from being able to change the ID. be able to read it but not write. Do i need to create another class etc to allow this and only expose this class to the other system (i.e. a business object) (i.e. ORM)?
i know alot of people are going to say just make the ID readonly. i.e.
public int ID { get; }
but if i do this then i cannot populate the ID from the code similar to above because in my DataAccessLayer i will not be able to set the ID as it is readonly.
thanks
Niall
You can create an internal constructor for the object that you can pass ID into, then set the flag for the Entities DLL that allows another DLL (DataAccessLayer) to be able to see and use the internal calls within this DLL. (InternalsVisibleTo attribute)
Look toward ORM tools which will assign ID of entity for you and your id property will look:
public class MyEntity
{
public virtual int ID { get; protected set; }
// other properties
}
if you choose this way, you don't need to worry about assigning properties and casting of types.

Categories

Resources