|
I understand what you are saying, however, in my case I have no other alternative but to use DataTables and DataSets.
The application I have gives us a list of available datasources (some from DB but could be a file)
The user has the option to combine two available datasources together to create one datasource.
At first, I went the long way of doing the merging by looping through each row and each column.
This was a bad idea for many reasons.
I found DataTable.Merge and passed in each dataset
Seemed quick and handled my schemas for each dataset.
But the draw back is memory.
So, can you (or someone) offer another way of doing this? Something fast and easy on the memory?
|
|
|
|
|
Hrmm,
If you consider that each data source would have unique tables and thus unique rows you could write each data source to the file system, use an Xml Streaming Reader and Writer and then create the new file as a combination of the other two. It is definitely a non-standard method but may work, would definitely be fast.
Need software developed? Offering C# development all over the United States, ERL GLOBAL, Inc is the only call you will have to make.
If you don't ask questions the answers won't stand in your way.
Most of this sig is for Google, not ego.
|
|
|
|
|
hmm, not a bad idea. I'll try that route real fast and see where it gets me.
I appreciate the time.
|
|
|
|
|
Sometimes we have items in the database which are mere choices. For example, I have a table as below:
TransportationTypeID Description
==================== ===========
1 Vessel
2 Air
3 Land
I can load these from the database but within my code I might have statements like:
If (medium == "Vessel")
{}
However, I think this is hardcoding. A person needs to know all the descriptions from the table to write statements such as these. Is there an alternative? Should I create dynamic enums for the description?
|
|
|
|
|
The most complete approach is to create a class TransportationType with the members Id and Descrption as ReadOnly properties. Then provide a static enumeration as well as static accessors.
However, to address your question, yes, "Vessel" would be hard-coding. Also, it would be better to check against the Id number if it so exists than the textual description. You would be surprised how often then get misspelled.
Need software developed? Offering C# development all over the United States, ERL GLOBAL, Inc is the only call you will have to make.
If you don't ask questions the answers won't stand in your way.
Most of this sig is for Google, not ego.
|
|
|
|
|
I do have a class named TransportationType which encapsulates the records from the table. I even have a TransportationTypeCollection which extends a generic Dictionary<int,> but I still need to know the id and what the description of the record at that id is. I was thinking of putting a global enum to facilitate the description to avoid misspelling but the problem is if a new record is added then I have to change the source code to include the new description and create an enum for it.
I guess some things need to be hard coded and we have to deal with it.
|
|
|
|
|
If adding a new record requires altering source you have a bigger problem.
Need software developed? Offering C# development all over the United States, ERL GLOBAL, Inc is the only call you will have to make.
If you don't ask questions the answers won't stand in your way.
Most of this sig is for Google, not ego.
|
|
|
|
|
But that is exactly what I want to avoid but seems as there is no other option. Just like I mentioned if I need to do something based on the type of the tranportation then what other option do I have? I can not even delegate the responsibility to the TransportationType itself because even then it would need to do a comparison as:
If (transType == "Vessel")
DoThis();
else
{
if (transType == "Air")
DoThat();
}
|
|
|
|
|
public abstract class Transportation{
public abstract void DoThat();
}
public class Air{
...
}
public class Vessel{
...
}
Then abstract the class creation using the Factory pattern. This one and only location could then be used for the hard-coding.
Need software developed? Offering C# development all over the United States, ERL GLOBAL, Inc is the only call you will have to make.
If you don't ask questions the answers won't stand in your way.
Most of this sig is for Google, not ego.
|
|
|
|
|
You missed a bit...make sure you derive from the base Transportation class:
public abstract class Transportation
{
public abstract void DoThat();
}
public class Air: Transportation
{
...
}
public class Vessel: Transportation
{
...
}
|
|
|
|
|
thx
Need software developed? Offering C# development all over the United States, ERL GLOBAL, Inc is the only call you will have to make.
If you don't ask questions the answers won't stand in your way.
Most of this sig is for Google, not ego.
|
|
|
|
|
Enums are helpful, but when trying to avoid 'coupling' they can create more problems than they solve. Remember they are basically a convenient textual representation of a numeric value (int by default) so you could just work with the numeric values thenselves. If you need the string for convenience, you could use a generic list of a class that has a string and an int properties, or a keyvalue pair/dictionary so you always have both available.
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
Generally I write an enum to match the table and add a comment that it must be kept in sync with the particular table.
I seem to recall that someone here recently (last few months?) posted about a technique to automatically update the table to match the enum, but I don't think that's quite the best solution.
Ideally the enum would be generated from the database, but how?
Certainly a process by which a code file is generated (at compile time) based on a query could be constructed, but it could cause a full rebuild even when the table doesn't change, so that may not be very palatable to some.
Emitting the enum at runtime doesn't seem like a workable solution because you wouldn't be able to program against it. (At least not until .net 4.0?)
|
|
|
|
|
That is indeed hard coding...and its best to avoid it whenever possible. An alternative to a hard coded string, enum, etc., you can use inheritance to solve the problem. Assuming that the TransportationType table is just a lookup of entries that classify records in other tables, you could do something like the following:
abstract class TransportationMedium
{
abstract string Name { get; }
abstract void Transport();
}
class Vessel: TransportationMedium
{
override string Name { get { return "Vessel"; } }
override void Transport()
{
}
}
class Air: TransportationMedium
{
override string Name { get { return "Air"; } }
override void Transport()
{
}
}
class Land: TransportationMedium
{
override string Name { get { return "Land"; } }
override void Transport()
{
}
}
static class TransportationMediumFactory
{
static TransportationMedium Construct(int typeID)
{
switch (typeID)
{
case 1: return new VesselMedium();
case 2: return new AirMedium();
case 3: return new LandMedium();
}
}
static TransportationMedium Construct(string type)
{
switch (type)
{
case "Vessel": return new VesselMedium();
case "Air": return new AirMedium();
case "Land": return new LandMedium();
}
}
}
class Program
{
void Main()
{
int mediumType = 0;
string intput;
Console.Write("Select medium (1=Vessel, 2=Air, 3=Land): ");
input = Console.ReadLine();
mediumType = Convert.ToInt32(input);
TransportationMedium medium = TransportationMediumFactory.Construct(mediumType);
Console.WriteLine("You chose " + medium.Name + " as your transportation medium.");
medium.Transport();
}
}
The factory in the implementation above still "hard codes" strings and ID's. This hard coding is centralized, and may be sufficient and maintainable if your application is small. If you need things to be more dynamic, you could easily pull out the mapping between type codes and ID's and the class implementations out into a configuration file, and change the factory implementation to dynamically, rather than statically, create the appropriate type via configuration. Then all hard coding is eliminated.
|
|
|
|
|
In a dialog box scenario this problem isn't evident. But if you have a MDI for and you want to open a form and get the data back to the mdi form you have a problem because you can't do a dialog and even if you could it would defeat the purpose of an MDI. So I was told to fire an event pack to the parent, but how to access the parent from the child especially since I thought that the child doesn't even know the parent
|
|
|
|
|
Why should the child not know its parent?
And what does that have to do with "fire an event back to the parent"; the child would merely raise the event, handling it is up to the parent.
|
|
|
|
|
ok well by firing i mean you are going to have the following line of code
this.uxBtnCreateOrder.Click += new System.EventHandler(this.CreateOrder_Click);
Now I am quite weak in custom events but isn't this where you decide to where the event will go? So I can't figure out how to send this to the parent.
|
|
|
|
|
That's done by the parent, not the child.
child.SomeEvent += new System.EventHandler ( this.SomeHandler ) ;
|
|
|
|
|
The child form can access it's parent by its MDIParent property. The downside of this is it is of type Form rather than the actual class that you have created so you can't access any custom properties or methods.
The best way, is for the Child to raise events. The parent can subscribe to them immediately after it has instanciated the child. Very simple example below.
using System;
using System.Windows.Forms;
public partial class FormParent : Form
{
public FormParent()
{
InitializeComponent();
IsMdiContainer = true;
FormChild frmChild = new FormChild();
frmChild.MdiParent = this;
frmChild.ChildEvent += new EventHandler<ChildEventArgs>(frmChild_ChildEvent);
frmChild.Show();
}
void frmChild_ChildEvent(object sender, ChildEventArgs e)
{
MessageBox.Show(e.Message);
}
}
using System;
using System.Windows.Forms;
public partial class FormChild : Form
{
public event EventHandler<ChildEventArgs> ChildEvent;
public FormChild()
{
InitializeComponent();
Shown += new EventHandler(FormChild_Shown);
}
void FormChild_Shown(object sender, EventArgs e)
{
PerformChildEvent();
}
void PerformChildEvent()
{
OnChildEvent(new ChildEventArgs("Child Event"));
}
protected virtual void OnChildEvent(ChildEventArgs e)
{
EventHandler<ChildEventArgs> eh = ChildEvent;
if (eh != null)
eh(this, e);
}
}
public class ChildEventArgs : EventArgs
{
private string m_Message;
public ChildEventArgs(string message)
{
m_Message = message;
}
public string Message
{
get { return m_Message; }
}
}
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
actually so what you are saying is that you shouldn't try to directly handle the form event on the parent, but rather you should handle the form event on the child form and in that event handler fire a custom event and that event you can handle on the parent form?
|
|
|
|
|
Sort of!
Anything that happens in the Child that the Parent (or anyone else) may be interested in should be handled by the Child raising an event that the Parent can subscribe to.
If there's already an appropriate event, then simply raise that by calling the OnXxx method for that event (it should also be overrideable if you need to do more with it and then call the base method). If not, create a custom event and raise that.
By the way, I included the customized event args for illustration, but if no data is needed to be passed, then you can declare the event as...
public event EventHandler ChildEvent;
and the raising becomes...
void PerformChildEvent()
{
OnChildEvent(EventArgs.Empty);
}
protected virtual void OnChildEvent(EventArgs e)
{
EventHandler eh = ChildEvent;
if (eh != null)
eh(this, e);
}
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
I guess my point was that for example formClosing is already an event and here we are actually going to raise another event. So in effect we are using and event to raise an event. It actaully worked for me that way and I appreciate your help but it seems kinda hackish to me. Is it accepted to do it that way?
|
|
|
|
|
If there's already an event then raise it directly by either
1. Doing whatever it is that raises the event.
For FormClosing you could call just Close() in the child.
2. Calling the OnXxx method that raises the event.
For FormClosing (set the event args parameters as you need to if there are any)
OnFormClosing(new FormClosingEventArgs(CloseReason.UserClosing, false));
3. Override the OnXxx method that raises the event and call your override.
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
} Note: Doing 2 or 3 will not cause the form to actually close as that is done in the Close method which internally calls the OnFormClosing(FormClosingEventArgs e) method.
[Edited for typos!]
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
Ok that's great actually but how can I override the FormClosingEvenArgs? I tried the following and I even created a special eventArgs that inherits FormClosingEventArgs but it doesn't accept it.
protected override void OnFormClosing(FormClosingEventArgs e)
{
orderedBooks = GenerateBookList();
CreateOrderEventArgs2 args2 = new CreateOrderEventArgs2(orderedBooks);
base.OnFormClosing(args2);
}
|
|
|
|
|
If you actually want the book list to be generated when the form closes then there are a couple of ways.
The simplest is to override the OnFormClosing (example 3 in last post). In the commented section after the base event is raised, check Cancel and if false, raise acustom event.
It is possible to customize the FormClosing. FormClosingEventArgs derive from CancelEventArgs, so we can do something similar. The code below works. It's a little more complicated than the first option but this way only the one event is fired.
public partial class Form1 : Form
{
public new event EventHandler<CreateOrderEventArgs> FormClosing;
private List<BookOrder> orderedBooks;
public Form1()
{
InitializeComponent();
}
List<BookOrder> GenerateBookList()
{
List<BookOrder> result = new List<BookOrder>();
return result;
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
EventHandler<CreateOrderEventArgs> eh = FormClosing;
if (eh != null)
{
orderedBooks = GenerateBookList();
CreateOrderEventArgs createOrderEventArgs = new CreateOrderEventArgs(
e, orderedBooks);
eh(this, createOrderEventArgs);
}
}
}
public class CreateOrderEventArgs : CancelEventArgs
{
private CloseReason m_CloseReason;
private List<BookOrder> m_OrderedBooks;
public CreateOrderEventArgs(
FormClosingEventArgs e, List<BookOrder> orderedBooks)
{
m_CloseReason = e.CloseReason;
Cancel = e.Cancel;
m_OrderedBooks = orderedBooks;
}
public CloseReason CloseReason
{
get { return m_CloseReason; }
}
public List<BookOrder> OrderedBooks
{
get { return m_OrderedBooks; }
}
}
public class BookOrder
{
}
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|