I'm having hard times trying to resolve cross-dependency between the projects in one solution.
The solution it's an asp.net application that has several projects.
The web project consumes the services of a sessionwrapper class in the SLN.Core project.
Declared like:
public sealed class SW
{
public static tblUserRow User
{
get
{
if (HttpContext.Current == null) return null;
return HttpContext.Current.Session["dtUser"] == null ? null : (tblUsersRow)(HttpContext.Current.Session["dtUser"] as tblUsers).Rows[0];
}
}
public static void User_Load(string userId)
{
tblUsers users = new tblUsers();
users.LoadByID(userId);
if (users.Count != 0)
{
HttpContext.Current.Session["dtUser"] = users;
}
}
}
The tblUserRow is part of the model definition of the users class (Strong typed datatable) in a separate models project. There are some other methods in the SW class, but aren't relevant.
So in SLN.Web I can access the user data like "SW.User.Name"
The models project is composed by the structures (model classes) and the DB engine classes in two different namespaces.
As seen above, the SW class depends on the models to declare User.
Up to here it's all OK.
But the fact is that model objects, need the User, Company, etc data when the classes are first created so they can get the default values. F.Ex: If you create a new invoice, it's nice to get the user (customer) assigned warehouse or payment type.
And as per working requeriments, the DB engine needs company or user data for making things like getting the DB (one per company) or saving log entries with user info.
Until the day that objects where passed on every call to DB engine classes or even methods, but now I'm refactoring this and I thought It would be cleaner and less memory consuming if that info could be got directly on the respective places from SW.
But there is cross-dependency between them. And as the SW members are declared static, so they can persist indepentent from session, I can't make an interface.
Any suggestions?
UPDATE: There was an issue with the scope of the user data that was previously solved, so I corrected here.
Also I'll add some more code for better understanding. From here VB, sorry dudes, but that's a nice model of diversity.
Example of the tblUser model in SLN.Models:
<DesignerCategory("Code"), System.SerializableAttribute()>
Partial Public Class tblUsers
Inherits TypedTableBase(Of tblUsersRow)
<DebuggerNonUserCodeAttribute()>
Public Sub New()
MyBase.New()
BeginInit()
InitClass()
EndInit()
End Sub
<DebuggerNonUserCodeAttribute()>
Private Sub InitClass()
TableName = TABLE_NAME
With Columns
.Add(New DataColumn(FIELD_ID, GetType(String)))
.Add(New DataColumn(FIELD_Name, GetType(String)))
...
'Added that last columns as example
.Add(New DataColumn(FIELD_Company, GetType(String)) With {.DefaultValue=SW.Company.ID})
.Add(New DataColumn(FIELD_Warehouse, GetType(String)) With {.DefaultValue=SW.Company.Warehouse})
End With
Dim keys(1) As DataColumn
keys(0) = Columns(0)
PrimaryKey = keys
End Sub
...
<DebuggerNonUserCodeAttribute()>
Public Sub LoadByID(Id As String)
Rows.Clear()
Merge(New SLN.DBEngine.Generic(SW.Company.Connection, doLog:=False).ExecuteQuery(COMMAND_LOADBY_ID, Id))
End Sub
...
End Class
Partial Public Class tblUsersRow
Inherits DataRow
<DebuggerNonUserCodeAttribute()>
Friend Sub New(ByVal builder As DataRowBuilder)
MyBase.New(builder)
End Sub
<DebuggerNonUserCodeAttribute()>
Public Property ID() As String
Get
Return DirectCast(MyBase.Item(0), String)
End Get
Set(value As String)
MyBase.Item(0) = value
End Set
End Property
<DebuggerNonUserCodeAttribute()>
Public Property Name() As String
Get
Return DirectCast(MyBase.Item(1), String)
End Get
Set(value As String)
MyBase.Item(1) = value
End Set
End Property
...
End Class
**Model classes are like this while I get a solution on EF for multiple DB. They where plain datatables.
Yes, there's another model class named Company that is also used in SW to provide company's data in session (multiple users, multiple companies logged onto)
You can see that on user construction, default values could be retrieved from SW. Same for other models like invoice heads, per example. That's the behaviour I want. By now all models that get default values, they get a complete object as a parameter of New(). Some models only want one field from a +25 flds object.
Also they use DBEngine for loading/querying/saving/deleting data.
In SLN.Web something like this may be seen (login):
SW.Company_Load(ddlCompany.Text)
sDescription = New Generic(SW.Company.Connection,False).ExecuteQuery("sp_Warehouse_LoadBy_Id",SW.User.Warehouse).Rows(0)("rDescription").ToString
Thaaats a roough example.
So SLN.Core.SW needs SLN.Models.tblUsersRow and SLN.DBEngine.Generic
And SLN.Models.tblUsers needs SLN.DBEngine but would also like to get SLN.Core.SW
...
SLN.DBEngine... needs SLN.Core.SW so he knows the DB to point to (some other things)
And SLN.Web need all of them. (sigh!)
Clear? (Errr...)
It is hard to understand your story clearly. But from what I get, your model need current_user to create objects (well, I don't get the business logic why this is required), and your web sln need the model for current_user.
Basically, the flow should be like this:
User class is defined
current_user is initiated
using the current_user, the model will initiate other objects
There are many ways available to accomplish this, however I propose 2 solution:
This implemenatation is to be done assuming you do dependency injection. Clean, and testable. This design is for Model solution.
public interface IUserProvider
{
User CurrentUser { get; }
}
public class ModelCreator
{
public ModelCreator(IUserProvider provider)
{
this.provider = provider;
}
IUserProvider provider;
public Invoice Get(){
User currentUser = provider.CurrentUser;
// do other
}
}
This implementation is to be done without dependency injection. Not clean, but mockable and easy to design. This design is for Model or Entity solution.
public static class UserProvider
{
private static Func<User> currentUserDelegate = new Func<User>(NullUser);
public static Func<User> CurrentUserDelegate
{
set
{
currentUserDelegate = value;
}
}
private static User NullUser()
{
return null;
}
public static User CurrentUser
{
get
{
return currentUserDelegate();
}
}
}
The usage:
public sealed class SW
{
private static User _currentUser;
public static User GetCurrentUser()
{
if (_currentUser == null)
{
tblUsers users = new tblUsers();
users.LoadByID(userId);
HttpContext.Current.Session["dtUser"] = users;
_currentUser = users[0];
}
return _currentUser;
}
public static void User_Load(string userId)
{
UserProvider.CurrentUserDelegate = new Func<User>(GetCurrentUser);
}
}
I finally solved the cross dependecy by moving the data entity classes related to those in SW class to the same CORE project.
Also moved the DB access engine classes to CORE, so in the models project there are only the entities and it can depend on CORE for DB access.
The CORE project does not depend on anything, as all it's entities are on it and also has the DB access engine.
So finally it was another problem of bad estructure design.
I also would like to give credit to Fendy, because the answer was agood one in other scenario.
#Fendy if you know a way for giving you credit, please tell me.
Thanks.
Related
While implementing a WPF Application I stumbled on the problem that my application needs some global data in every ViewModel. However some of the ViewModels only need reading access while other need read/write access for this Field. At First I stumbled upon the Microsoft Idea of a SessionContext like so:
public class SessionContext
{
#region Public Members
public static string UserName { get; set; }
public static string Role { get; set; }
public static Teacher CurrentTeacher { get; set; }
public static Parent CurrentParent { get; set; }
public static LocalStudent CurrentStudent { get; set; }
public static List<LocalGrade> CurrentGrades { get; set; }
#endregion
#region Public Methods
public static void Logon(string userName, string role)
{
UserName = userName;
Role = role;
}
public static void Logoff()
{
UserName = "";
Role = "";
CurrentStudent = null;
CurrentTeacher = null;
CurrentParent = null;
}
#endregion
}
This isn't (in my Opinion at least) nicely testable and it gets problematic in case my global data grows (A think that could likely happen in this application).
The next thing I found was the implementation of a Mediator/the Mediator Pattern from this link. I liked the Idea of the Design Norbert is going here and thought about implementing something similar for my project. However in this project I am already using the impressive Mediatr Nuget Package and that is also a Mediator implementation. So I thought "Why reinvent the Wheel" if I could just use a nice and well tested Mediator. But here starts my real Question: In case of sending changes to the global data by other ViewModels to my Readonly ViewModels I would use Notifications. That means:
public class ReadOnlyViewModel : NotificationHandler<Notification>
{
//some Member
//global Data
public string Username {get; private set;}
public async Task Handle(Notification notification, CancellationToken token)
{
Username = notification.Username;
}
}
The Question(s) now:
1. Is this a good Practice for using MVVM (It's just a Feeling that doing this is wrong because it feels like exposing Business Logic in the ViewModel)
2. Is there a better way to seperate this so that my Viewmodel doesn't need to inherit 5 to 6 different NotificationHandlers<,>?
Update:
As Clarification to what I want to achieve here:
My Goal is to implement a wpf application that manages some Global Data (lets say a Username as mentioned above) for one of its Window. That means because i am using a DI Container (and because of what kind of data it is) that I have to declare the Service #mm8 proposed as a Singleton. That however is a little bit problematic in case (and I have that case) I need to open a new Window that needs different global data at this time. That would mean that I either need to change the lifetime to something like "kind of scoped" or (breaking the single Responsibility of the class) by adding more fields for different Purposes or I create n Services for the n possible Windows I maybe need to open. To the first Idea of splitting the Service: I would like to because that would mitigate all the above mentioned problems but that would make the sharing of Data problematic because I don't know a reliable way to communicate this global data from the Writeservice to the readservice while something async or parallell running is happening in a Background Thread that could trigger the writeservice to update it's data.
You could use a shared service that you inject your view models with. It can for example implement two interfaces, one for write operations and one for read operations only, e.g.:
public interface IReadDataService
{
object Read();
}
public interface IWriteDataService : IReadDataService
{
void Write();
}
public class GlobalDataService : IReadDataService, IWriteDataService
{
public object Read()
{
throw new NotImplementedException();
}
public void Write()
{
throw new NotImplementedException();
}
}
You would then inject the view models that should have write access with a IWriteDataService (and the other ones with a IReadDataService):
public ViewModel(IWriteDataService dataService) { ... }
This solution both makes the code easy to understand and easy to test.
In my website there are dozens of calls made to a sql database and each time it passes along the ID of the user requesting data. I'm attempting to set up a singleton class that will only need to make one call to the database to grab the person's ID along with other user attributes that only need to be grabbed once.
I thought I had everything set up properly and it seemed to be working so I moved the code change into production and have gotten calls from several users saying when they log in, they are all being identified as me. This is based on the welcome message at the top of my home page that says "Welcome ", and everybody's userName is showing as me.
My singleton is below. After getting the call I started debugging, what I have found is that the formValues() method where I thought the values are being set is never getting called. The only thing that does get called is the public Instance method. I'm guessing that's obvious to everybody that knows what they are doing :).
I don't think this is relevant, but the instance of the variables is being called in my code like: formValues.Instance.firstName.
So how close am I? Is this thing salvageable?
public sealed class formValues : System.Web.Services.WebService
{
static readonly formValues instance = new formValues();
public string userName;
public string firstName;
public string personID;
public string secBlur;
public int admin;
public int fafsa;
public int staff;
static formValues()
{
}
formValues()
{
//This retrieves the person logged into windows/active directory
FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
userName = id.Name;
// Grab this user's firstname, personID, and Admin status
string mySQL = "exec get_userData #userName";
string cf = System.Configuration.ConfigurationManager.ConnectionStrings["DistrictAssessmentDWConnectionString"].ConnectionString;
SqlConnection connection = new SqlConnection(cf);
SqlCommand command = new SqlCommand(mySQL, connection);
command.Parameters.AddWithValue("#userName", userName);
connection.Open();
SqlDataReader dr = command.ExecuteReader();
if (dr.HasRows)
{
while (dr.Read())
{
personID = dr["personID"].ToString();
firstName = dr["firstName"].ToString();
admin = Convert.ToInt32(dr["admin"]);
secBlur = dr["secBlur"].ToString();
fafsa = Convert.ToInt32(dr["FAFSA"]);
staff = Convert.ToInt32(dr["staffSec"]);
}
}
connection.Close();
}
public static formValues Instance
{
get
{
return instance;
}
}
}
The problem is that these properties (fields, actually) are in a singleton:
public string userName;
public string firstName;
public string personID;
public string secBlur;
public int admin;
public int fafsa;
public int staff;
...along with the fact that they get populated in the constructor. That means the first time you create the class, it gets populated. If you re-use that same class instance as a singleton, the constructor will never get called again, which means that the values populated will be set once and remain forever.
In other words, your user data is a singleton. Unless you will only have one user ever, that's not good.
First, I would separate the class that retrieves the data from the class that contains the data.
The data might look like this:
public class UserData
{
public string UserName { get; set; }
public string FirstName { get; set; }
// ..etc...
}
That model contains the data. It does not contain the code to populate the data.
Then, create a class that retrieves the data. It shouldn't retrieve the data in the constructor. The constructor is for creating the class. It's not where we would put the stuff that the class actually does.
That class might have a method like this:
public UserData GetUserData()
...which would create an instance of UserData and return it.
For what it's worth, for most scenarios we don't need to create a singleton.
Suppose you have this class:
public class SqlUserDataProvider
{
UserData GetUserData()
{
...
}
}
If the constructor doesn't do anything "heavy" like read data or files, you could just create a new instance each time you need one. It's less efficient than using a single instance, but the difference is usually so minutely trivial that it's not worth considering.
Or, you can create a single instance and re-use it. In that case you're using it as a singleton, but technically it isn't one. A singleton is class written so that it is only possible to create a single instance of it. Most of the time there's just no reason to do that. It's extra lines of code to strictly enforce a restriction on how we use the class. It can potentially make code less maintainable and harder to debug. So it's extra work for either no benefit or negative benefit.
Basically, you want to do a cache. For http requests you need to check if value is already in cache, if it is not - read from the database, otherwise use cache.
You can start with built-in Cache
As for singletons, simplest solution is to implement them using Lazy. Here is good article
The instance object is created just once on an application lifetime.
So your private constructor formValues(), where you get the FormsIdentity, is actually executed just once after application starts up first time ever.
After that , for all incoming requests, the already populated instance is given out.
That's why you see the same username, for any further requests.
Since the requirement is per-user basis, and not something global across application, "singleton" probably wont help. Thanks.
I'm trying to implement this architecture for the first time in a Winform. So I have a simple but very important question for me.
Take a simple example. I want the form to retrieve a user list and to allow a modification of the phone number.
I have this for the first step (simplified and I normally use interfaces)
public Form1()
{
InitializeComponent();
UserService _userService = new UserService();
listBoxUsers.DataSource = _userService.GetAllUsers();
}
class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Phone { get; set; }
}
class UserService
{
UserRepository _userRepository=new UserRepository();
public Dictionary<int, string> GetAllUsers()
{
DataTable dtbl= _userRepository.AllUsers();
//Some code here
return dict;
}
}
class UserRepository
{
public DataTable AllUsers()
{
//Sql query
return dtbl;
}
}
Now by selecting a user in the lisbox, I'm able to display some information as the Phone number. When I'm changing the phone number, I need a method called UpdatePhoneNumber to update the SQL database.
But, where to place it? User or UserService (I don't talk about the SQL query, just the logic)
And after that, how to access (here or somewhere else in the app) to this user property to display it in the form? Directly with _user.Id (User must be instantiated in the form) or implement a _userService.The id which retrieves User.ID (in this case Form knows only UserService class).
Many thanks for your precious help
Put all Methods working on the User's data in the user class. Ask yourself the question what the user can do? Put all the logic which controlls the users in UserService like GetUserById, GetAllUsers, CreateUser and so..
Put all the method which the user can perform in the User class.
Or lately i was building such kind of thing and i merged User and UserServices into one and made the UserServices class method static so i can access them without instantion of the User.
Hope this help.
Here is what your basic 3-layered app looks like.
UI (your form and ui supporting objects)
BLL (GetAllUsers, SaveUser, DeleteUser, etc)
Data (ADO, EF, etc)
In your particular case, you really looking for Master-detail concept. A master usually the one where you display list of users
// Master
var _userList = Service.GetAllUsers(); // List<UserModel>
userGrid.Datasource = _userList;
I will not discuss it here but you can set bindings so that click on grid will result in detail control being populated. Or manually
// detail
UserModel model = master._userList[currIndex];
txtFirstName.Text = model.FirstName;
txtPhone.Text = model.Phone;
// . . . .
Now, of course, you're about to change the text box and save user...
// detail
UserModel model = master._userList[currIndex];
Service.SaveUser(model);
Master.Reload();
This is general idea, how this is done. If you follow, you have distinct layers. UI calls Service, which calls Data. For example, you have BLL
// Service
private IUserDataProvider _provider;
public List<UserModel> GetAllUsers()
{
var data = _provider.Get<User>();
// massage your 'data' and return List<UserModel>
. . . .
}
your provider might return some unwanted data, so you can use BLL to trim it and return only appropriate data. But you don't know what provider is doing inside. May be it is doing Ado.net or Entity Framework. Hence a true separation of layers.
This is actually 2 questions in one.
I have an asp.net mvc application where I have to load a list of Modules, its just a simple list with ID, modulename and a class name to render it on the view with font awesome.
My model is like this:
public class Module
{
[Key]
public int Id { get; set; }
public string ModuleName { get; set; }
public string FontAwesomeClass { get; set; }
}
Because the module list is a Partial View that will render some icons on the top navigation bar, I dont want that for each refresh of the app, it goes to the DB, so it must be cached(I am using Azure REDIS Cache, not relevant for the question anyway), so instead of calling the DB context directly from the controller, I am calling a Cache Class that will check if the cache object exists, if not it will retrieve it from DB, if it does, it will return it from cache.
This my solution structure:
http://screencast.com/t/uayPYiHaPCav
Here is my controller Module.cs
public ActionResult GetModules()
{
return View(Cache.Module.GetModules());
}
As you can see the Controller does not have any logic where to get the data from.
Here is the Module.cs (on the Cache Namespace)
public class Module
{
private AppDataContext dbApp = new AppDataContext();
//Load modules from cache or from database
public static List<Models.Module> GetModules()
{
IDatabase cache = Helper.Connection.GetDatabase();
List<Models.Module> listOfModules = (List<Models.Module>)cache.Get("Modules");
if (listOfModules == null)
{
return dbApp.ModuleList.ToList();
}
else
{
return listOfModules;
}
}
}
Here I have a compiler error which I am not sure how to best fix it:
Error CS0120 An object reference is required for the non-static field,
method, or property 'Module.dbApp'
So that was my first question.
The 2nd question is more about the design pattern, do you consider this correct or not? the way I am trying to get the data from Cache, and its actually the Cache class which checks if data is on it or if it has to go to the DB.
First Question: make your private member static
private static AppDataContext dbApp = new AppDataContext();
2nd Question: your cache strategy seems pretty standard. The only thing is that you might want to expire cache data. For example, the cached data can get old and the longer it stays in the cache the older it gets. You might at some point want to expire it and get fresh data again.
Update:
#EstebanV for code sample (this off the top of my head, don't assume that it compiles):
/**
ICachedPersonDao abstracts away the caching mechanism
away from the core of your application
**/
public CachedPersonDao : ICachedPersonDao
{
private IPersonDao personDao = null;
public CachedPersonDao(IPersonDao personDao)
{
this.personDao = personDao;
}
public Person GetPersonById(int id){
bool isInCache = CACHE.SomeFunctionThatChecksInYourCache(id);
if (isInCache)
{
return CACHE.SomeFunctionThatReturnsTheCachedPerson(id);
}
else
{
//Well it's not in the cache so let's get it from the DB.
return this.personDao.GetPersonById(id);
}
}
}
/**
IPersonDao abstracts database communication
away from the core of your application
**/
public class PersonDao : IPersonDao
{
public Person GetPersonById(int id)
{
/** Get the person by id from the DB
through EntityFramework or whatever
**/
}
}
Usage:
In your controller, use ICachedPersonDao if you want to attempt to get from cache or use IPersonDao if you want to get it directly from the database without checking the cache.
Like I said, you should learn Dependency Injection it will help "inject" these dependencies into the classes that uses them.
I say again, this is off the top of my head. It won't compile. It's just to illustrate the concept.
struggling To achieve a solution for a basic Task:
working with more than one Sql Data table, as a source, for a WebSite application...
that's what leads me here once again... seeking for an Experienced C# .net Developers Help.
i was just trying to add some basic logic for a proper implementation,Like using
a dedicated namespace & classes, To Hold reference for All DATABASE tables,
(before i try working / learning about Entities Framework approach.)
i would like to try implement same of basic features of EF ...by my self, and that way... i will also learn how to properly work with classes.
as it is so far ... structured : with my little knowledge
a 'helper'.. namespace , say the company name is: HT technologies
so I've named the namespace HT_DbSchema ...that contains :
tables names
public sealed class HTDB_Tables
{
public const string Customers= "Customers";
public const string Times= "Times";
}
tables IDs
public sealed class HT_tblIDs
{
public const int tblCustomersID = 1, tblTimesID = 2;
}
tables Columns Lists ...(just one example)
public class HTDB_Cols
{
public class tblCustomers
{
public const string CustId = "custId",
CustName = "custName",
CellPhone = "cellPhone" .... etc'
}
}
and as all those 3 classes are serving all projects ..
there's another helper class for constructor Per Table For the Current Project
public class DBMetaDetails
{
public struct DbTable
{
public string TableName { get; set; }
public int TableID { get; set; }
}
}
so still these are all construction / helpers Classes and are separated from the project,
now for current project
What is The Appropriate way to get it done, using above Classes and constructor within a project
(i could name those templates)
what i was doing so far to implement some order is :
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
{
.... some other App inits here
}
else
{
}
// this method should be the one that instanciates the DbTable struct
//and set the values of tables name and "ID"
setTablesReferences();
}
And Here's where the confusion starts :
in a day by day usage i want to try implement it in a WebSite application :
public void setTableReferences()
{
DBMetaDetails.DbTable CustMeta = new DBMetaDetails.DbTable();
DBMetaDetails.DbTable TimesMeta = new DBMetaDetails.DbTable();
}
so now i need to set CustMeta & TimesMeta details(ids & names)
the struct has a kind of a template structure a kind'a systematic technique to initialize and assign values, so it brings some decent order to my logic with it's existence .
so what is the confusing part ?
from one point of view(safety), i need those tables detailes to be readonly
so DbTable.TableID, and DbTable.TableName would not get overWriten by mistake.
having said that, there should be only one place it could be SET ... a dedicated section of the application, like setTableReferences() above,... there i might add :
CustMeta.TableID = HT_tblIDs.tblCustomersID
CustMeta.TableName = HTDB_Tables.Customers;
on the other hand, i need the information of the tables to be Accessible,
so if let's say i would like to add those DataTables into a DataSet
DataSet ALLTablesSet = new DataSet();
// assuming the SQL actions already been taken in another method previosly...
// so DataTable is already retrived from DB
//...but only as a short usage example:
AllTablesSet.Tables.Add(new DataTable(CustMeta.TableName));
My Question is What is the Correct Way to work with structs ... as in My Scenario,
So in one section of app: you would initialize - assign it with a value privately.
and from other sections of the app you could use its value (Only For Readings)
so that way, the application will not be able to access it's value for writing,
only by reading values, i think it should be trough another (Public ReadOnly) Variable.
so that variable was meant to be exposed ...and it's value could not be "harmed"
If I understand the question correctly, the way I would prevent other code from modifying it is by removing the setters on the properties. However, you still need to set them at some point, so rather than removing the setters completely, you can just make them private. For example:
public string TableName { get; private set; }
If you do this, the only place you can set this data is within the struct itself, so you would need to create a constructor that took the initial values you wanted. So something like:
public struct DbTable
{
public DbTable(string tableName, int tableId)
{
this.TableName = tableName;
this.TableID = tableId;
}
public string TableName { get; private set; }
public int TableID { get; private set; }
}