c# DAL class and business layer class - c#

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.

Related

asp.net class library that talks to ef and customizable

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

How to map to internal properties using Automapper?

we've been using Automapper for sometime and we think it is great utility, thanks for creating it!
However, we have a question:
Question
"How do you configure AutoMapper to map a source property to an internal destination property?"
Background
In our layered architecture, Dto objects never leave the Data Access layer, only Domain objects are allowed to pass in and out of the Data Access layer. Thus, from a domain POV, domain objects shouldn't contain any database knowledge. However, in reality database Ids are very useful to carry around - expect the 'business-layer' developer shouldn't know about them.
Solution: add the database Ids to the domain object but market them as internal so that they aren't exposed to the 'business-layer'. Next expose the Common layer (which owns the domain objects) internals to the Data Access layer. Problem solved. Expect we can't figure out how to get Automapper (> v3.3.0) to work with our internal properties.
In, version 3.3.0 BindingFlags were exposed, which use to solve the problem.
Example
Common.Dll
public class Person
{
public Parent Father { get; set; }
internal int FatherId {get; private set; }
}
DataAccess.dll
internal class PersonDto
{
public ParentDto Father { get; set; }
public int FatherId {get; private set; }
}
In our Profile class we have CreateMap<PersonDto, Person>();
Edit 1 - Fixed a typo in the return type of Father.
Edit 2 - Added more info..
In the Common.Dll, we have Services something like this:
public class ParentService
{
public Parent GetFather(Person person)
{
return repo.Parents.FirstOrDefault(parent => parent.Id = person.Father.Id);
}
}
And in the Business.Dll we have developer's using the Services something like this:
var father = parentService.GetFather(son);
// use father separately or assign it to the son. Like so:
// son.Father = father;
The whole point is, we don't want the business developer's to have access to son.FatherId from the Businssess.Dll nor do they have access to the Dto object that created the domain object.
Thus, all the 'database' knowledge is encapsulated within in the various Common.dll Services or in the DataAccess.dll.
Thanks.
This question is answered here.
I quote the answer for your convenience:
Just set the ShouldMapProperty property of your configuration object
in the initialize method.
Here is an example using the static API, however, you should be able
to achieve the same in a similar fashion by using the non-static API.
Mapper.Initialize(i =>
{
i.ShouldMapProperty = p => p.GetMethod.IsPublic || p.GetMethod.IsAssembly;
i.CreateMap<Source, Target>();
});

Automatically set added properties when retrieving database objects in C#

I am extending a large C# project that connects to SQL Server.
In the database I have an Inventory table which has a foreign key manufacturer_id from the Manufacturer table.
I have added some properties to the Inventory class from the Manufacturer table because the app must continue to send Inventory objects but now include Manufacturer information as well.
public partial class Inventory
{
public string ManufacturerName {get; set;}
}
In my InventoryRepository I now call my SetManufacturerName method whenever I return Inventory objects and must remember to call it in any new methods.
Is there a way to call a method automatically whenever an Inventory object is retrieved from the database?
I am unable to change anything in the database.
You can call your desired method in the constructor of the class. It will ensure that whenever an instance of object is created your method is called
public partial class Inventory
{
public Inventory() { YourMethodCall(); }
public string ManufacturerName {get; set;}
}
You don't have to call anything upon object creation, just provide a non-trivial implementation of the property
public string ManufacturerName
{
get
{
// your code here,e.g.
return this.Manufacturer.Name;
}
...
}

Where do derived or inferred properties belong in an application?

I'm building an app using code first and generating the DB.
I can no longer modify the DB so, I can't add/change columns and tables. But the Domain Model (not sure if I'm using the term correctly) requires new properties (that are part of the domain) that can be inferred from the database data, but do not exist explicitly.
My database stores sales info for houses. So I have two tables, Houses and Sales. The tables are related by houseID. Now I want houses to have a property called LastSaleDate, but I can't change the underlying database.
So, How would I properly construct this new property and add it into the appropriate layer? Here is what my poco/entities look like. Just pseudo coded...
[I am trying to learn all I can about the tools and methods I use. I may be completely wrong on all my assumptions and maybe I am to add it to my pocos. If that is the case please explain how that would work]
[Table("HOUSE_TABLE")]
public class house {
//some properties
public int HouseID {get;set;}
}
[Table("SALE_TABLE")
public class sale {
//some properties
public int HouseID {get;set;
public int SaleID {get;set;}
public datetime SaleDate {get;set;}
public virtual House House {get;set;}
}
I almost feel like this would create 2 levels of mapping. Though, I don't believe I've ever seen this done in any code I've seen online.
poco -> AutoMapper?? -> entities -> Automapper -> viewModels
This logic most likely belongs on the Entity. Entities should have both data and behaviour. What you seem to be describing is some behaviour that is exposed as a property. So, you should add a property for the derived value to your entity. By default, if the property only has a getter, then EF will not try to map the value to the database.
For example:
[Table("HOUSE_TABLE")]
public class house
{
//some properties
public int HouseID {get;set;}
public virtual ICollection<Sale> Sales { get; set; }
public DateTime LastSaleDate
{
get
{
return this.Sales.OrderByDescending(s => s.SaleDate).First();
}
}
}

CRUD operations on complex DTO

Need an advise on the "best" way to implement Update and Delete operations on complex nested DTOs. For very simple example, suppose we have this structure:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Employer Company { get; set; }
}
public class Employer
{
public string Name { get; set; }
public string Address1 { get; set; }
public string City { get; set; }
public string State { get; set; }
}
An update to Person as per Employer here can mean several things:
1. Previously there was no Employer for Person and we need to do insert to DB to introduce new Employer.
2. There was an Employer previously and we are just updating the Employer's inner Data
3. Employer has been removed from Person
Question:
If you have a domain/business compnent object something like PersonBusinessComponent with some method like PersonBusinessComponent.Update(Person)
What is the best way to identify which scenario being executed and apply changes -- meaning if it is a delete operation then we'll call some EmployerDALC.Delete method or if it is an Insert then obviously EmployerDALC.Insert etc...
I understand that one option is to get current version from Database and then tediously compare for existence of every nested object within Person, but I hope there is some better way or even probably more generic way that can be implemented to handle any such operations in the whole solution.
Note: I am not using MS Entity Framework.
It depends on the architecture of your system. Is this a Procedural model, an ActiveRecord model or a Domain Model? I see you're using DTOs so that would imply a Domain model.
If so then your business logic (inside the 'Services' tier) would be responsible for orchestrating the operations, for example:
public interface PersonManager
{
void CreateNewPerson(Person person);
void DeletePerson(Person person);
void ModifyPerson(Person person);
// ... and so on .../
}
The PersonManager would then be responsible for examining the object and working out what to do with it based on the method run.
It would then defer down to its own business logic layer (which can converse with the DAL) to work out exactly how that should be achieved. For example with the Modify method it can query the DAL to get the current Employer's for that Person, defer to a ModifyEmployer if the employer has changed etc:
public void ModifyPerson(Person person)
{
var currentEmployer = DAL.Employers.Get(Person.Employer.EmployerID);
if (currentEmployer != person.Employer)
{
// Try and get a matching Employer from the appropriate Service (liaising with the DAL)
var employer = EmployerManager.GetEmployer(person.Employer.EmployerID);
if (employer == null)
{
// ... Create a new employer
}
else if (employer != person.Employer)
{
// ... Update existing employer
}
}
// ... Now go ahead and handle any changes to the person
}
Off the top of my head I can't think of any particular package to handle this for you, generally I'd say it's all in the architecture of your system and how the BL talks to the DAL, but I'm sure one of the brain-boxes here will come up with some better suggestions :)
Hope that might help a little bit!
K.

Categories

Resources