C# How to access a class from two different forms? - c#

I am having a big problem wich I cannot solve myself.
I have got two windows forms running at the same time and a separate class. To interact with the class I use this code in both forms:
private Entities entities = new Entities();
I use that in one of my forms, like so:
int hp = entities.Get_HP(CurrentEntity);
Here hp will be for example 90 or 57... But when I do the exact same thing in the other form, then it will thow an exception saying that entities.Get_HP(CurrentEntity) is null. The debugger (vs 2012) says the same.
This only happens in one form, not the other.
I really hope someone can help me with this, because I'm clueless.
Thank you, Dion Dokter.

Each time you say "new" you're getting an entirely unique instance of the object. What you want is the same instrance between the two different windows. You could use events to pass around information, or a static method somewhere, or have the windows have a custom constructor(s) with parameter(s) to share the object(s).
These are core concepts. Someone can help further if you detail your usage of your program, specifically how these forms are opened.

In Form1 change you Entities declaration to something like;
private static Entities entities = new Entities();
public static GetEntities() { return entities }
In Form2
private Entities entities;
private bool entitiesSet = false;
Where you're gonna use entities;
if (!entitiesSet)
entities = Form1.GetEntities();
Just make sure there is no code path that attempts to access methods/properties of entities before it is set in Form2 and this should do it. Not sure where this implementation stands with regard to good or bad practice as I don't work with controllers/winforms but it will definitely work.

Related

Using ref in (whole) partial class

I got some confusion about "the right way" to use a reference in a partial class.
Basically i wrote a WPF program which has different Menus. Every Menu got the same Viewmodel and some data-related object class. In my case i call the Object "DataModel" which i want to use as reference in every menu. I just came across a problem when ich switched my DataModel from a static object to the desired instance for every Menu as input ref. (i still want to use one and the same DataModel for every menu though...)
But in the "lower" methods it says that _dm is simply not defined.
Code shortly summarized as:
public partial class FormatWPF : UserControl
{
public FormatWPF(DataModel _dm)
{
InitializeComponent();
if (this.DataContext == null)
{
this.DataContext = _dm.g1.MVM;
}
}
// here come several Methods with which i want to calculate stuff and "manipulate" the DataModel
private void Steinformat_berechnen()
{
_dm.g1.FormatNr = _dm.g1.FormatAnzahl + 1;
}
//....
}
Shortly said i want to use the _dm which is given as input ref in the Constructor of the class object for every other method in the whole partial class as well (is it really necessary to define this ref for every method ?) Using the DataModel as static seemed so easy for me.... but basically it is "wrong" ?
Thanks in advance for some help and tips about doing it the right way.
Maybe i was a little bit unclear. The thing is i want to use just one DataModel for all the menu and my whole project. Nevertheless i dont want to make it as static ( there occured some other confusion in later parts of my code... ) So basically i have to give in the DataModel as ref for all the Menus...
Concerning your answer: I know the possibility to define another
private Datamodel _dm;
in the namespace..
But im not quite sure about:
1)won't i got here some additional "memory" usage by defining another DataModel for every menu ? becuase it is somehow "big"
2)when i now calculate data in the _dm, will it change for the "complete" program ? like in the former static Model ?
I hope to make the DataModel static then is not the "right answer" to my problem because i just wanted to get away from this somehow ... hm
Best regards
Knally
Yes, static is very wrong if the DataModel is a per-instance thing (static means all the instances would be using the same value); but it can still be an instance field:
private DataModel _dm;
public FormatWPF(DataModel dataModel)
{
_dm = dataModel;
// the rest of your constructor code here
}
Now you can use _dm in all of your other instance methods, and everything should be fine. If you only ever need _dm.g1, you could perhaps store that value as the field, instead of the model itself.

Communication between two classes via form

I am using a Windows Form MainForm which calls the following:
FileSystemLayer FSL = new FileSystemLayer();
DatabaseLayer DBL = new DatabaseLayer();
What I want to do:
(inside the DatabaseLayer class)
String SomeString = MainForm.FSL.AnotherString;
The problem
The FileSystemLayer FSL is inaccessible due to its protection level
I've tried
public FileSystemLayer FSL = new FileSystemLayer();
public DatabaseLayer DBL = new DatabaseLayer();
But it gave the result
Inconsistent accessibility: 'DatabaseLayer' is less accessible than
field 'MainForm.DBL'
So I'm hoping someone can give me some advice on how to communicate between the two classes.
It seems that the DatabaseLayer class is defined as internal so if you want to make a property of that type to be accessible publicly, you should define the type (DatabaseLayer) public too, or you may make your property less visible by defining it as internal.
But as also it seems that you are using some kind of layering it wouldn't be the right way to achieve what you are looking for.
That message is telling you that while the DBL member field of the main form is declared as public the type itself (DatabaseLayer) is declared as something other than public, most likely private, or internal
So you can solve the problem by modifying the the DatabaseLayer class and making it public class DatabaseLayer.
That said, the main purpose of encapsulating functionality into the file system layer and the database layer respectively is to loosen coupling. But if you expose one to the other directly and allow one to call into the other than you're sort of throwing the benefit out the window. You should consider alternative approaches to facilitating communication between the two layers.
After trying several suggested solutions, that I couldn't manage to apply, I instead changed the hierarchy of the class calling like described below. Thanks to the people taking time to help me towards a solution.
(Them Paint skillz)

C# Where to load initial data in an object?

Similar to this question:
C# Constructor Design but this question is slight different.
I have a class Customer and a class CustomerManager. When an instance is created of the CustomerManager class I want to load all the customers. And this is where I got stuck. I can do this several ways:
Load all the customers in the constructor (I don't like this one because it can take a while if I have many customers)
In every method of the CustomerManager class that performs database related actions, check the local list of customers is loaded and if not, load the list:
public method FindCustomer(int id)
{
if(_customers == null)
// some code which will load the customers list
}
Create a method which loads all the customers. This method must be called before calling methods which performs database related actions:
In the class:
public LoadData()
{
// some code which will load the customers list
}
In the form:
CustomerManager manager = new CustomerManager();
manager.LoadData();
Customer customer = manager.FindCustomer(int id);
What is the best way to do this?
EDIT:
I have the feeling that I am misunderstood here. Maybe it is because I wasn't clear enough. In the CustomerManager class I have several methods which depends on the local list (_customers). So, my question is, where should I fill that list?
What you are describing is "lazy loading".
A simple approach is to have a private property like this:
private Lixt<Customer> _customers;
private List<Customer> Customers
{
get
{
if(_customers == null)
_customers = LoadData();
return _customers;
}
}
Then, you refer to Customers internally. The customers will be loaded the first time they are needed but no earlier.
This is such a common pattern that .Net 4.0 added a Lazy<T> class that does this for you.
I that case, you just define it as a private like this:
private Lazy<List<Customer>> _customers = new Lazy<List<Customer>>(LoadData);
Then, you simply refer to your customers in code:
_customers.Value
The class will initialize the value with your LoadData() method.
If you are not on .Net 4.0 yet, the Lazy<T> class is very easy to implement.
Use a property for accessing the customers. Have that check if the customers are loaded.
Well, it depends. All your options have advantages and disadvantages.
The good thing about options 1 and 3 is that the user has full control over when the (lengthy) data loading operation is performed. Whether option 1 or 3 is better depends on whether it makes sense to create the Manager and load the data later or not. Personally, I prefer a separate LoadData method if it's a lengthy operation, but that might be a matter of taste.
The good thing about option 2 is that the data will not be loaded if it is not needed. The drawback is that the (lengthy) load occurs as a side-affect of the first access, which makes your program "less deterministic".
In principle, all the options you have presented are fine and valid choices. It really depends on your requirements.

Public Static Variables c# Used correctly?

As mentioned in a previous post, I am currently learning C#, and for my first (well second if you include hello world and some messing about) real project, I'm going to create a basic EPOS system and then expand upon it..
My intention is to have all pricing, Cashier details, sales transactions, etc.. stored within a MySQL Database (I can move from PHP to C#, but I can't bring myself to moving away from MySQL!)
What I would like to check is the following:
I have 2 forms(at present)
A login screen (where the user enters their PIN number)
The main Sales screen.
When the user logs in, I am going to authenticate them against the details held within my database, and if successful, then I will load the main sales screen.
I need to somehow transfer information around between forms, so what I have done is created a new class file called variableStore.cs in here, I am going to be storing the userID, userName (so I can have "Currently Logged in: John Doe" on each form status bar.
But I will also be using the same file for transferring "transaction total", etc.. around between forms.
Is this the correct (ok, not correct, but is this how you would do it?) way of doing things?
I would not do this way you said. Is this a web application?
You should keep the user information and the business layer information separately. This will give you enough freedom to change the user information in the future if required.
For passing the transaction total, you should query the information from the database and show it to the web page. Can you do this?
You can also pass data using the following:-
1. constructor
2. objects
3. properties
4. Delegates
When talking about authentication and authorization, you should create your own implementation of IPrincipal and IIdentity, which are then set within the Thread (Thread.CurrentThread).
The IPrincipal goes on the Thread and it holds onto your IIdentity. Your implementation can be queried to determine if the user is authenticated and what the user is allowed to do (see IsInRole).
As for using global variables to store information, that is not a good idea. However, you're starting out, so it might be good for you.
Alternatively, you could create public properties on your Forms where you set and, after the form is closed, get the results of user action on the form (don't forget, a form is an object just like anything else). So if form A instantiates form B, shows B modally, then gets control back after form B is closed, form A could then get the results (whatever they are) of user interaction from the properties on B.
public class B : Form
{
// Set when the user completes a sale and closes the form with the OK button.
public SaleItem Sale{ get; private set;}
}
This is much better than using a global store for variables. If I were doing this, I'd use a dependency injection framework like Unity to get instances of classes that provide for functions such as sales within my application.
No, that is not how I would handle things.
A much better way of handling is passing the values between forms either through the constructor, properties, or methods.
Constructor
public class SalesForm : Form
{
public SalesForm(string userName)
{
Text = "Currently Logged In: " + userName;
}
}
Now, on the Login Form button click handler (after authenticating the user):
var mainForm = new SalesForm(userName);
mainForm.Show();
Property
public class SalesForm : Form
{
private string _userName = null;
public string UserName
{
get
{
return _userName;
}
set
{
_userName = value;
if(!String.IsNullOrEmpty(_userName))
Text = "Currently Logged In: " + _userName;
}
}
}
And again, on the Login Form button click handler:
var mainForm = new SalesForm();
mainForm.UserName = userName;
mainForm.Show();
Method
public class SalesForm : Form
{
public void SetTitle(string userName)
{
Text = "Currently Logged In: " + userName;
}
}
And:
var mainForm = new SalesForm();
mainForm.SetTitle(userName);
mainForm.Show();
It is normally preferred to use the IServiceProvider pattern, but in small and trivial cases, static would be OK.
For a small, simple application when you're just getting started, static variables can help get things running, but it's not a habit you want to get into. You might start by writing down all of your state variables in one place, but then step back and take the time to think about where you actually use them. If some of the variables are only used in one small part of the program, try to think of ways to hide them from the rest of the program, such as by putting them in a class that only that part of the program is given an instance of. As you write your program, take breaks periodically, look at your classes and think about the following:
Encapsulation : Is my class doing a well-defined job or is it trying to do all sorts of different things? If you can't immediately figure out what the job-description of the class is, then it's probably doing too much. Consider breaking the functionality off into smaller pieces that you can work on individually.
Insulation: Is my class exposing information that other classes shouldn't need to know about it? I should only tell other classes what they need in order for them to use me for my job. I also need to prevent other classes from interfering with my job as best I can. If other classes use me incorrectly, I should complain loudly (throw exceptions) so that the developer realizes that something is wrong.
Non-repetition: Do I have pieces of code that look very similar, with only slight modifications between them? Try to find a way to consolidate these pieces of code into a single method and call that method from each location. If you ever find yourself fixing a bug and having to go to multiple locations in the code to apply the fix, this is a sign that you're repeating yourself. Invest the time to fix this and it will be beneficial in so many ways in the future.
These principles are all designed to help manage complexity, by helping you to understand your code and by limiting the possibility for bugs by minimizing the number of possible interactions between portions of code. Enjoy learning. :)

C# static database class?

I have a Database class which contanins the follwing methods:
public bool ExecuteUDIQuery(string query) // UDI = Update Delete Insert
public bool ExecuteSelectQuery(string query)
public bool ExecuteSP(string sp, string[,] parms)
public int ExecuteSPReturnValue(string sp, string[,] parms)
The results of the methods are stored in private datasets or datatables. These objects are defined as getters.
There're about 10 classes which use the Database class. Every class creates an object of the class Database. Now i was thinking to make the Database class static. Is this a good idea? If so, why? Of not, why not?
If I understand, the database class has some properties that store the result of the query? If so, you cannot make them static, since that is not thread-safe. If the result of a query is stored in these properties, what would happen if a second query would execute right after the first? It would be stored in the same static variable. The same goes for a web application: the result of another user browsing the site would change the results of the first user.
EDIT: To summarize, do NOT make the class static when you store the result of the queries in static variables, especially not when the class is used in a website, as the properties value will be shared amongst all visitors of your website. If 20 visitors do a query at the same time, visitor 1 will see the results of visitor 20's query.
In your specific example, I'd advise against making the class static: you're keeping state in the Database class, and by making the class static, that state will be shared amongst all classes using your Database. In your current setup, each Database instance keeps its own state, so there's no problem with Database calls interfering with each other.
If you'd refactor the Database class to return the datasets when doing a method call, you'd be fine making it static: there would be no stateful information left in the Database class.
But since this is not the case: no, don't make the class static.
In addition to the others comments about thread safety there is also the issue of paralellization. In your case you won't be able to open several connections to the database at the same time and you won't be able to perform multiple paralell queries, even if thread safety of the results isn't an issue.
So I agree with the others, don't make a static class out of it.
Making the class static may be convenient, but creating new instances of it probably won't be an expensive operation so there probably isn't much to gain performance-wise either.
Edit:
I saw in a comment that you want to use your class on a web site. In that case you REALLY shouldn't do this. With a static database class you will only be able to safely serve one request at any time, and that is not what you want.
It depends on what kind of database or ORM that you're using. But in my experience it's seemed like a good idea but ended up shafting me. Here's how it did for me in LINQ-to-SQL:
I had a repository class that had a static variable to a data context. It worked at first, but when I had to make many more repository classes I ended up getting bugs as I hacked along. It turns out that data context in LINQ-to-SQL caches up all results and there is no way to refresh them. So if you added a post in a table in one context, it won't show up in other that cached that table. The solution was to remove the static modifier and let the repository create the context in the constructor. Since the repository classes were constructed as they were used, so would a fresh new data context.
You could argue that static variables leaves less footprint in memory, but the footprint for a data context is quite small to begin with and will be garbage collected in the end.
Contrary to the answer post.
I've built a webframework with a static database access it works great and gives great performance.
You can check out the source code at http://www.codeplex.com/Cubes
If you are just executing queries against the DB, then yes make it static. You only have to create an instance if this object needs to keep some sort of state.
If you have a static method you need to keep track of instances when you open and close the database.
So what you probably want to do is have a static Method called instance or current instance. And within you create a new instance of your db-class returning it in the static method.
Your methods good for static usage. I think, you have no trouble to convert them to static methods for now.
but later maybe you will need to manage transaction. leaving the transaction management to a class is saves lots of time I think. and this scenario is best fits with a nonstatic class.

Categories

Resources