File Management: Handled by the Data Access Layer of Business Layer? - file

So, I am working on this web based app following the Repository model, a wannabe DDD dork, using StructureMap.... blah, blah, blah...
One aspect of the application allows users to upload and manage files.
Where, what layer, should be responsible for managing the saving/ deleting of these user files?
The Business Layer,
or the Data Access Layer...?
It, for whatever reason, doesn't seem a straight forward answer...
Historically, I just slapped it in the GUI, but striving to be more programmaticall correct and rethinking what should handle these service. Maybe I just answered my own question...

I create a separate layer "Storage Access Layer (SAL)" .... getting file information from DAL I passed that to SAL and SAL return me the correct file ....so if someday I switch to Amazon web services from web hosting storage , I will just change the classes in SAL , plug the DLL and ready to go ....because the user will upload the file in same way as before so UI is not changed..... business rules are enforced same as before so BLL is not changed....Database has not changed and information of file is saved same as before so DAL is not changed...... only thing changed was the protocol to access the file....so just change the SAL

I would put it in the business layer, though if it were me, I'd end up making calls to the DAL with regards to the files each user has uploaded. I'd keep track in the database of the file names and locations for each file a user uploads.

I put mine in the DAL since we considered the files data in which to update or query, just through a different "protocol" that being System.IO.
More specifically, I made a FileManager class that handled all the basics and even had a couple of constants in place so it was easy enough to change path locations for development and production environments, since they were drastically different.

Dillie-O - Furthermore, if the application ever switched to storing files from the IO to the DB, the DAL is a more logical place. Some flexibility...

It's in DAL full stop.
Business logic should not have IO dependency on your environment.
You put it in business logic, next time you want to use that piece of "logic" but end up on an environment with no file IO permission you'd be toast.

Related

How to remove EntityFramework.SqlServer Reference from WebApplication project in a DDD Solution

I have a highly standardized project in DDD (Domain-Driven Design), so it means that each layer has it's responsibilities and no layer knows other than itself and the Domain Layer.
Here's the structure of my project:
My Infra.Data layer is responsible for connecting with the Database, and i'm persisting using EntityFramework.
My problem is: in order to make it work with SQLServer Databases, i need to add a reference to EntityFramework.SqlServer in my WebApplication layer, which breaks my separation of concerns concept, as you can see below.
Even having the same reference in my Infra.Data layer, which is where it only should be, as you can see below.
If i remove the EntityFramework.SqlServer reference from the WebApplication layer, it stops working, and throws exception every time i try to persist data, as you can see below.
I need to know how to remove this reference to keep separation of concerns, because the way it is now, i'll have to change my WebApplication if i want to change my persistence. My Web layer is prohibited to even have anything with the word "EntityFramework" in it. I want FULL separation of concerns to change any layer without affecting no other.
If i register my <entityFramework> provider in my Web.config file, it will only works if i have the EntityFramework.SqlServer in the project, but without the EntityFramework.SqlServer reference on the WebApplication, it miss namespaces and complain about it.
Note: My project also connects to MySql Databases successfully, and i don't need no references to MySql.Data or any other MySql library in my WebApplication layer, as expected.
Please help me, my DDD/Separation of Concerns OCD is cracking on it, thanks.
You can!
Just create this class in your Infra.Data project:
internal static class ForceEFToCopyDllToOutput
{
private static SqlProviderServices instance = SqlProviderServices.Instance;
}
When you do this you let the compiler know that the specific resource is used and should be available in the bin folder.
Some consider this a hack but it's useful if you want to keep your layers free from infrastructure concerns.
You can read more about this here: DLL reference not copying into project bin
EDIT:
All you'll need now is to copy the connection string from your Infra.Data app.config to your WebApplication web.config
<connectionStrings>
<add name="DatabaseConnectionString" providerName="System.Data.SqlClient" connectionString="..." />
</connectionStrings>
You would not be able to get rid of Entity-framework configuration and the required DLL in your Web-application :
Lets say your infrastructure layer and domain layer need to depend on Entity-framework. This means these two libraries need to have physical access to Entity Framework DLLs(Have Entity-framework package installed) and configured.
When you run your web application which has dependency on infrastructure and domain libraries, all Dlls used by underlying libraries (infrastructure and domain) need to be present physically and configured otherwise you will have run time issue(program might be compile-able but you will get run-time errors).
Morale of the story : If application x [Irrespective of the layer it belongs to] has dependency to library y,z and library y,z rely on some dll and require configuration, for application x to work at run-time you need to have all dlls needed by y,z available and provide their configuration (web.config) in your instance.
You can obviously provide some workarounds such as copying the files directly and providing separate config files for each layer but I strongly advise against it because it would get extremely messy and very hard to maintain in the long run.

Where to put a separate business logic class or classes in CakePHP 3?

I am designing a new application and plan to use CakePHP 3. Typically when designing an application on top of a PHP MVC framework (CakePHP, CodeIgniter) I have implemented a separate set of classes that represents the business layer or service layer (depending on what words you like to use). Thus, the stack:
-- Views
-- Controllers [really just another part of the views; code-behind from C# land]
-- Business layer [where business logic goes, because business logic spans multiple domain objects and isn't appropriate for a single Model/DAO]
-- Models [aka Data Access Objects]
...with domain objects (now "Entities" in Cake PHP 3) traversing between the layers.
I see that Cake PHP 3 still lacks any concept of a business layer in the default architecture, which is disappointing but hardly insurmountable. But after all that, my question is actually rather pedestrian. It is: Where do I put MyBusinessLayer.php? In Cake PHP 2 I would have put it in app/Lib, and loaded it up with
App::Import('Lib', 'MyBusinessLayer');
What is the equivalent in CakePHP 3, and how do I load it? I realize I could just stick it any old place and require_once(), but I wonder if there is a way that is more consistent with Cake PHP standards. This question could just as easily apply to a ten-line utility class, but in my case it applies to the business layer.
Your business layer can be put anywhere under the src directory. For example you could have a folder called src/Core or src/MyBusiness or you could have multiple folders like src/Command src/Handler, it is up to you how you want to architecture your application other than serving a web request or accessing data in the database.
Classes put inside any folder inside src will be automatically loaded if given the right namespace.
// in src/MyBusiness/BusinessRules.php
namespace App\MyBusiness;
class BusinessRules
{
...
}
You can automatically load this class from another use the use keyword:
// In another file
use App\MyBusiness\BusinessRules;
...
$rules = new BusinessRules();
CakePHP does not make assumptions for you when it comes to this kind of objects as they usually are very specific to your application. It does offer a wide variety of tools that can help you build a better architecture more rapidly and with less code. For example using the Event system for Aspect Oriented Programming, the configuration traits for creating adaptable implementations or the Collection library for working with data using a functional approach.

Using a Reference Table Service in a WPF Application

For past projects(the last few have been web using asp.net mvc) we created a service that caches our reference tables(as required) to be used primarily for dropdown lists.
Now I'm working on a desktop application.An upgrade from vb6/sybase to vb.net/sql server
I'm trying out WPF.
I started down the same path building up my DAL. one entity for each reference table.
I'm at the stage now where I want to setup the business layer (some reference tables can be edited)
And I'm not sure if I should follow the same process which is to use ReferenceTableService to "manage" the reference tables.(interacts with the DAL, Controller)
This will be an application that sits on a share that multiple users run.
What's the best way to deal with the reference tables? Caching them doesn't seem to be an option. Should I simply load them as each user opens up a new form in the application? Perhaps using a "ReferenceTableService"?
In this case, the Reference Table Service is thin layer in the application. Not a process running elsewhere.
I haven't done much WPF (be interesting to see what the WPF Gurus think) but I think your existing approach is sound and I don;t see why you should deviate from it.
Loading up on app start sounds reasonable; you just have to think about the expected lifetime of a user session vs the expected frequency of changes to the reference data.
Caching: if the data comes from a central service you could always introduce caching there.

App.Config vs Custom XML file

I have read a lot of statements like "you shouldn't clog your app.config file with custom settings". However, I was under the impression that this was exactly the purpose of the file?
Is it just indeed a preference thing? Or are there any real benefits (other than separation of settings) by using a custom XML file, as apposed to the app.config file? If you need to explicitly separate settings would it better to use a custom ConfigurationSection rather than opting for a custom XML file?
I would like to here other peoples thoughts on this.
Some people tend to go a bit overboard on custom config section handlers, in my humble opinion.
I tend to use them only when I need something that is very structed; and that is used/written by 3rd parties (i.e. I want to do some extravagent validation on it).
I think you can quite happily use app.config/web.config for all relevant settings, and use separate XML files when it is very clear that is a separate component of the app.
Have a look at the Application Settings Architecture, the app.config is for Configration regarding the Application, thats quite a general term though.. So I would suggest you look into the Application Settings Files.
I would not store settings like "load database on startup or not" in the app.config. I would rather use an Alternative Storage like Application Settings for this, don't confuse Application Configuration with Settings, even though you might want to do that, Don't. app.config is supposed to have configration regarding lower level things like Database connection, Membership Provider or any other Application Critic information.
Most settings tend to fall into one of three camps:
Technical settings that affect the internal behaviour of the code, e.g. database connection string, data file path, logging switches, error handling switches, etc.
Business settings that affect the business logic of the product, e.g. "are users allowed to access the CRM Module?"
User-specific profile values, e.g. "is this user allowed to access the CRM Module?".
The natural place for type 1 is in app.config or web.config, and the natural place for types 2 and 3 is in the database.
App.Config are good for configuration that are application specific : path to database is a good example. The rest should be out of it.
One thing you might want to do is to create user-specific files, you can then use custom xml that will be saved into an IsolatedStore.
In my opinion I consider app.config to be good for deployment-time settings such as the location of the database, or an IP address or location of critical data file, etc. User settings like font, color, behavior preferences should go in a different file which you can easily create and save with Xml serialization.

LLBL Gen Pro 2.6 and Auditing

I am using LLBL Gen Pro v2.6 and am attempting to create a means of auditing changes made to the database. Now, I know that LLBL Gen has auditing built into it using AuditorBase and dependency injection. The question I have is; I need to track not only the stuff that LLBL Gen exposes as auditable, but also the User who made the changes. From what I've seen there isn't a built in way of gathering this information. Has anyone used LLBL Gen's built in auditing and determined a way to do this?
Wayne E. Pfeffer
I have used LLBLGens Auditing classes. Determining the user is really something that you will have to handle. There are too many variables for LLBLGen to actually do this for you. How are your users handled? Is this a winforms or asp.net application?
The best solution would be to store the UserId in a session variable or static variable depending on which is more appropriate for your application. In your implementation of the Auditing class you can just pull the UserId from its storage place.
Another potential solution would be to override the Entity Class or the Data Adapter classes and pass the UserId in to your save methods. However, this would be a lot more work.
In my WinForms app, I accomplish this by creating a custom IPrincipal and stick that on System.Threading.Thread.CurrentPrincipal when a user logs into the application. Then, I can easily grab that from inside my LLBLGen auditing classes.
We're also about to implement auditing of changes to the db, and have the same issue of adding the user_id to the auditlog. I can see you can do the pull-approach, e.g. fetchingn the user_id from the web session (we're building a web application), but this would completely mess up the layering of the application, as I see it!?
I.e. if the DAL pulls data information from the presentation layer (web session), I won't be able to use the DAL in other contexts?
Best regards,
--thomas

Resources