|
Thanks for confirming.
I wish I could give you an extra upvote for doing it by example.
My knowledge map sadly says "Here be monsters" where it should say IL.
So that's added on my todo list.
|
|
|
|
|
You're welcome. I do find that dropping down to the IL can be a real eye opener at times.
|
|
|
|
|
Do you have any reading to recommend, or should I just get my hands dirty?
|
|
|
|
|
Just get your hands dirty. I learned IL by writing simple, predictable console applications that exercised different parts of the language and then I looked to see what was produced. Of course, I was lucky enough to be forced down this route because I wrote a code generator back in about 2004 and I had to really get my head around the way IL worked to fully understand what I was producing.
|
|
|
|
|
I have the following objects:
public class Parent
{
public BaseChild Child {get;set;}
}
public class BaseChild
{
}
public class ChildOne : BaseChild
{
public string Member {get;set;}
}
"Parent" is mapped to a "Parent2" type from a different module (which has the same member BaseChild).
Mapper.CreateMap(typeof(Parent), typeof(Module2::Parent2));
Mapper.CreateMap(typeof(BaseChild), typeof(Module2::BaseChild));
Mapper.CreateMap(typeof(ChildOne ), typeof(Module2::ChildOne ));
I'm creating a Parent object:
Parent parent = new Parent
{
Child = new ChildOne { Member = "Test" }
}
And try to convert:
object parent2 = Mapper.Map(parent, parent.GetType(), typeof(Module2::Parent2));
I get the following exception from auto mapper:
----------
{AutoMapper.AutoMapperMappingException: Missing type map configuration or unsupported mapping.
Mapping types:
ChildOne -> BaseChild
Test.ChildOne -> Test.BaseChild
----------
I need this mapping to work in order to be able to convert objects from a new "Parent2" type (in the 2nd module) to an old one.
How do I make it support inherited types of members in a converted class?
|
|
|
|
|
Hi,
I am able to use API DllImport("user32.dll") for FindWindow, GetCursorPosition then use sendkys to enter some number\text into an other GUI application ... through its Title & Class (ie: Windows Calculator!
However if I don't use API Mouse to move in other sections ... I can't not go directly them (with Autoit I can use with Title & Advanced Class = Advanced (Class): [CLASS:Button; INSTANCE:72] )
My question is there any way I can do that with Vsual C# and How?
Thanks to any help
|
|
|
|
|
Well, it AutoIt, there is code behind the scenes that is parsing and interpreting that "Advanced (Class): [CLASS:Button, INSTANCE:72])" stuff. There is NOTHING in the Windows API that has any idea what that string means or what to do with it.
You're asking about how to write the code that AutoIt has inside that does just that. For that, you would have to ask the people who wrote AutoIt. Good luck with that!
|
|
|
|
|
Might be the way I asking wasn't right, I do work well with Autoit ... but I have to work with Visual C# now! I am not expert in Visual C#, that was why I would like to know there is a similiar way to access direct an instance of a GUI or not? I thought Visual C# a well-known SW should have a better way than a free Autoit (it can't even build a DLL or a distribution application)
If there isn't a way, then I will have to use mouse method to move to the area I want to access ... but this ia the bad way, because if the people move the GUI to other position or change the screen resolution ... the mouse will move to wrong location
I hope that you aren't upset because of a people who just wants to know there is any thing available
modified 16-Mar-14 16:08pm.
|
|
|
|
|
Member 10636998 wrote: I would like to know there is a similiar way to access direct an instance of a GUI or not
No, there isn't. The only way you've got is the one you're already using, FindWindow, ...
|
|
|
|
|
Hi Dave,
In this case I don't have to search for it any more!
Thanks for the confirmation.
|
|
|
|
|
I want to create an application where I can load the excel file or the set the path in the code(hard coded) and the program will create the table in SQL Server. The data in the top column will be the name of the fields.
Assuming that Database is already created and the name of excel file will be the name for the table.
So I want to know how to approach this task and what things I need to consider.
Thanks
|
|
|
|
|
It's not something I've done, but...
Loading Excel data to a DataTable is pretty easy:
public static System.Data.DataTable LoadExcel(string path, string columns = "*", string sheet = "Sheet1$", bool verify = true)
{
if (verify)
{
if (!File.Exists(path)) throw new IOException("The input file does not exist: " + path);
if (!GetExcelSheetNames(path).Contains(sheet)) throw new ArgumentException("The requested sheet does not exist: " + sheet);
}
if (string.IsNullOrWhiteSpace(columns)) columns = "*";
System.Data.DataTable dt = new System.Data.DataTable();
using (OleDbConnection con = new OleDbConnection(GetExcelConnectionString(path)))
{
con.Open();
string cmdStr = string.Format("SELECT {0} FROM [{1}]", columns, sheet);
using (OleDbCommand cmd = new OleDbCommand(cmdStr, con))
{
using (OleDbDataAdapter da = new OleDbDataAdapter(cmd))
{
da.Fill(dt);
}
}
}
return dt;
}
public static List<string> GetExcelSheetNames(string path)
{
List<string> sheetNames = new List<string>();
using (OleDbConnection con = new OleDbConnection(GetExcelConnectionString(path)))
{
con.Open();
using (DataTable sheets = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null))
{
foreach (DataRow sheet in sheets.Rows)
{
if (sheet["TABLE_NAME"].ToString().Contains("$"))
{
sheetNames.Add(sheet["TABLE_NAME"].ToString());
}
}
}
}
return sheetNames;
}
private static string GetExcelConnectionString(string path)
{
return string.Format(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0}; Extended Properties=Excel 12.0", path);
}
And then you need to do is create the DB table from the DataTable. And that is already done as well...if not by me: http://darrylagostinelli.com/2011/06/27/create-a-sql-table-from-a-datatable-in-c-net/[^]
Finally, bulk copy the data over:
public static void LoadSql(string strConnect, string tableName, DataTable table)
{
using (SqlConnection con = new SqlConnection(strConnect))
{
try
{
con.Open();
using (SqlBulkCopy bulk = new SqlBulkCopy(con))
{
bulk.DestinationTableName = tableName;
bulk.WriteToServer(table);
}
}
finally
{
con.Close();
}
}
}
Those who fail to learn history are doomed to repeat it. --- George Santayana (December 16, 1863 – September 26, 1952)
Those who fail to clear history are doomed to explain it. --- OriginalGriff (February 24, 1959 – ∞)
|
|
|
|
|
It's bad practice! It could cause several problems, like: unable to add table with the name of existing one, unable to manage the tons of tables, etc.
Please, refer this: Maximum Capacity Specifications for SQL Server[^]
Tables per database are limited by the number of objects in a database. Database objects include objects such as tables, views, stored procedures, user-defined functions, triggers, rules, defaults, and constraints. The sum of the number of all objects in a database cannot exceed 2,147,483,647 (MS SQL Server 2012).
|
|
|
|
|
It may not be perfect practice, but it's something quite useful - I keep several "odds and ends" in Excel format that should really be in SQL, and being able to transfer the data from the one to the other makes life a lot easier (I'm tidying up the code in my link at the moment, because it's pretty poorly written). Once I'm finished, I'll transfer half a dozen of my Excel sheets to SQL and convert the spreadsheets to C# forms instead.
I suspect it's not something he wants to do every day, but he wants to avoid the potential errors involved in a manual transfer. Thinking about it, I may knock up a utility to do it as well - prototyping the DB is a lot easier in Excel than in SSMS where you have to keep switching about to / from design mode.
Those who fail to learn history are doomed to repeat it. --- George Santayana (December 16, 1863 – September 26, 1952)
Those who fail to clear history are doomed to explain it. --- OriginalGriff (February 24, 1959 – ∞)
|
|
|
|
|
Ok, i can agree with it only in case when it happens once on a long time.
BTW: Both your answers have been upvoted!
|
|
|
|
|
OriginalGriff wrote: and being able to transfer the data from the one to the other makes life a lot easier
Just to clarify... The OP was asking about creating a table not loading data.
So are you referring to creating tables or loading data?
And if you are creating tables are you referring to a standard business table or just something like an enumeration table?
|
|
|
|
|
The way I read the OP's question he wanted to use a Excel Sheet to create a "standard" SQL table and populate it with the data - so my answer did just that. Mind you, he could just leave off the last stage if he doesn't want to transfer the data as well.
Those who fail to learn history are doomed to repeat it. --- George Santayana (December 16, 1863 – September 26, 1952)
Those who fail to clear history are doomed to explain it. --- OriginalGriff (February 24, 1959 – ∞)
|
|
|
|
|
So then you are creating tables from your spreadsheets...
How do you determine field sizes for numerics and text?
How do you determine what names to use for the fields?
How do you specify a primary key?
How do you specify indexes?
|
|
|
|
|
Not too bad, really.
The fields sizes (or at least, safe field sizes) can be inferred from the datatypes Excel returns - have a look at the code at the bottom of the link in my original post, it works pretty well.
The names can be retrieved as the column names from SQL - and nearly everybody uses those!
You can't assign primary keys automatically - excel doesn't have the concept - so the table is going to need some manual post processing. To be expected I guess! Exactly the same with indexes and foreign key relationships etc. - again Excel doesn't know what they are.
But for getting the basic structure right, and filling it in, then transferring a working structure complete with sample data it's not a bad idea, and could well be a lot easier than the equivalent in SSMS (which tends to annoy me a lot more than it should if I tweak my data when I'm designing data storage )
Those who fail to learn history are doomed to repeat it. --- George Santayana (December 16, 1863 – September 26, 1952)
Those who fail to clear history are doomed to explain it. --- OriginalGriff (February 24, 1959 – ∞)
|
|
|
|
|
Good morning wise ones.
You've probably seen DB code akin to this before:
public List<int> GetSomeNumbers()
{
List<int> x = new List<int>();
using (SqlConnection)
using (SqlCommand)
using (SqlDataReader)
while (reader.Read()) x.Add(reader[0]);
return x;
}
Which would populate and return a list from the first column of the query. I've left the detail out, and yes a cast would be required. Another possibly better approach would be this:
public IEnumerable<int> GetSomeNumbers()
{
List<int> x = new List<int>();
using (SqlConnection)
using (SqlCommand)
using (SqlDataReader)
while (reader.Read()) yield return reader[0];
return x;
}
The reason it might be better is because it immediately returns on each read so that if I do something like send the result straight over a network I can do this is a 'streaming' approach which would be faster and not require as much memory. The reason it might not be as good is that IEnumerable is inherently more confusing. The call doesn't even get invoked until something tries to iterate it and that can catch us all out.
I'm starting to adopt the latter approach more and more, but questions arise because of the more complicated execution flow. In particular, what happens if I do this:
foreach (int x in GetSomeNumbers())
{
if (x == 0) break;
}
This is the bit I'm unsure about. Assume that a zero arrives a long time before then end of the result set. IEnumerables tell us when we're at the end of can give us the next item, but what happens if the consumer bails out before the end? There's no way (that I know of) to tell the iterator function we've concluded. Where does this leave the disposal of the reader, command and connection?
Be happy, its Friday!
Regards,
Rob Philpott.
|
|
|
|
|
Looking at section 8.8.4 of the C# Language Specification[^]:
A foreach statement of the form
foreach (V v in x) embedded-statement
is then expanded to:
{
E e = ((C)(x)).GetEnumerator();
try {
while (e.MoveNext()) {
V v = (V)(T)e.Current;
embedded-statement
}
}
finally {
}
}
Therefore, regardless of whether your statement block breaks the loop, throws an exception, or runs to completion, the enumerator object will always be disposed.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Very nice answer Richard.
I had a feeling that IDisposable may be at work. Unfortunately I tend to think along the lines that an IEnumerable is merely something you iterate over rather than something that returns a disposable iterator (or enumerator if you prefer - I think the parlance is different for .NET than STL etc.)
So I guess what's happening now is the when the iterator gets disposed, it's essentially doing the same as a yield break to force its way out my own while loop. The implicitness of that bothers me slightly, because my condition of .Read() will always go to the end of the result set. And in fact the ability to break the loop is being delegated to outside.
I really should try all this out in the debugger.
So that's cleared that up and I've got one less thing to worry about now. Thanks!
Regards,
Rob Philpott.
|
|
|
|
|
Nice Answer to allow ones learning for a friday thanks
Every day, thousands of innocent plants are killed by vegetarians.
Help end the violence EAT BACON
|
|
|
|
|
Nice Question to improve ones learning for a friday thanks
Every day, thousands of innocent plants are killed by vegetarians.
Help end the violence EAT BACON
|
|
|
|
|
Rob Philpott wrote: I can do this is a 'streaming' approach which would be faster and not require as much memory.
Of course if that is a concern then caching the results would be far better than either choice.
|
|
|
|