Jump to content
Xtreme .Net Talk

Nerseus

*Experts*
  • Posts

    2607
  • Joined

  • Last visited

Everything posted by Nerseus

  1. The only thing I've seen that does what you describe is a dedicated install/uninstall program. The three big ones are: Microsoft (built in installer with Visual Studio), InstallShield, and Wise install. There are a number of free ones as well. Keep in mind that none of them just "knows" what gets installed. The person making the installer must tell the installer what's there, and what should get uninstalled. Most will know about folders and files but if you have registry settings, you'll have to tell the installer which branch and keys you have. If you write custom config files, save files, etc., you'll have to tell the installer about them so it can do cleanup later. Fancier installs will even prompt the user on uninstall with something like "Extra config files were detected at [folder name]. Would you like these removed?" I know of no "monitor" that will simply scan/check everything - registry, files, etc. to let you know what's been installed. -ner
  2. I've used both - a simple return type of List<T> and a class that derives from List<T>. Here's how I decide (if-based, because I'm a programmer :) ) If the list is "internal" only - just a quick return type so I can iterate over the list, use the simple List<T> return type. Else create a class. More often than not, once I have created the class I find a reason to add a method or two. -ner
  3. I believe you can use "this.DesignMode" or "Me.DesignMode" to check, and prevent, accidental writing of things like the Text property. I've used that on classes that inherit from Form but should work for custom/user controls. -ner
  4. In addition to the math issue you've noticed, I'll add that rounding in .net may or may not work as you expect for money. There are generally two ways to round when you encounter a 0.5 number - that is, a number that is exactly halfway between going up or down. By default, .net takes the engineering approach, which makes every other number go up and the opposite go down. So: Math.Round(0.5) = 0 Math.Round(1.5) = 2 Math.Round(2.5) = 2 Math.Round(3.5) = 4 In general, currencly values will always go up at 0.5. When dealing with money, you want this: Math.Round(0.5) = 1 Math.Round(1.5) = 2 Math.Round(2.5) = 3 Math.Round(3.5) = 4 You'll have to make sure you specify the MidpointRounding type. Just a note :) -ner
  5. What DataType is column TimeSheets.Date? Silly question, I know... but you're comparing the column to a varchar in your query so I thought I'd ask. If it's a datetime and your variables are both datetime, then I'd think it would work just fine. Keep in mind that datetime DOES have a time portion so if your table values have time stored, then your "BETWEEN" will likely not include records on the @enddate date. For example: Row 0: Date = '01/11/2007 1:32pm' Row 1: Date = '01/12/2007 2:32pm' If @start = '1/11/2007' and @end = '1/12/2007' then it will NOT pick up Row 1. The two common fixes are: 1. Change the query to not use BETWEEN, but use something like: TimeSheets.Date >= @start and TimeSheets.Date < (@enddate + 1 day) You'll use something like DATEADD(d, 1, @enddate) for that last bit. 2. Change the @enddate to be the END of the date you're checking: SET @endDate = '1/12/2007 11:59:59pm' TimeSheets.Date BETWEEN @start and @endDate -ner
  6. I'm not sure which column it is, but it doesn't seem too hard to figure out on your end. Here's what I'd look at: Looking at your ChangeControls table and see which columns don't allow NULL (marked as NOT NULL). If there are only a few, this makes things easier. In method UpdateChangeControls, look at the parameters and see which of the columns have value DBNull.Value instead of a valid value. That should pinpoint the current issue. Some columns seem fine, like "Status" which are hard-coded to have a value like "Open" To help find these types of issues earlier, you can define the columns in your DataSet to have the same properties as those of your DB table. Suppose your table has column "Name" as NOT NULL. When you define your DataSet, just make sure to have the column not allow nulls as well. You set this through the "MinOccurs" property - using a value of zero will make it not allow nulls. If you need to temporarily allow nulls, you can set the nillable property to true. That will allow you to put DBNull.Value in the non-null column until you try and commit - then the nillible=false property will prevent you from saving. -ner
  7. Not sure what you mean by "dotnet not c#" - maybe you mean VB.NET? If so, the article I linked to actually mentions this next article, which has the same code in VB.NET: http://www.dotnet247.com/247reference/msgs/10/51694.aspx Good luck!! -ner
  8. The term you're looking for is "rounded rectangle" - that might help when you go googling for samples. I've attached a sample C# project that should do what you want. The project contains two main files: Form1 and ExtendedGraphics. ExtendedGraphics was taken directly from CodeProject, found here: http://www.codeproject.com/cs/media/ExtendedGraphics.asp Form1 shows just one way to draw the rectangles. I chose to override the OnPaint event of the form, which gives you a Graphics object. Some people use timers (for a game possibly) and will create their own Graphics object. There are some samples on these forums on how to get that working. It's an artform, in a way, to get fast graphics to draw and often comes down to just how much drawing you'll be doing. -ner GUIDrawing.zip
  9. My initial thoughts went like this: Wow! (pause) I wonder if it will be useful at all... (pause) Wow! I bet there's a LOT of good info to be gleaned by seeing their code and how they implemented/documented things. I've never had any trouble with the .Net framework regarding bugs. Now 3rd party software, that's where you want the source! -ner
  10. That's right, FULL source for libraries like System.Windows, System.Web, System.Data (ADODB) and more!!! Expected later this year. See article below for more info: http://weblogs.asp.net/scottgu/archive/2007/10/03/releasing-the-source-code-for-the-net-framework-libraries.aspx -ner
  11. The syntax you're looking for is: EXECUTE @text = SP_HELPTEXT... But a few problems. 1. You can't create a local "text" variable. You can replace "DECLARE @text text" with "DECLARE @text varchar(max)". NOTE the (max) syntax is SQL 2005 specific. Doesn't matter, it won't work :) 2. The assignment usage you're trying only takes the RETURN value and puts it into a variable. The sp_helptext proc returns the text via a SELECT statement. So, assuming the sp_helptext call works, it RETURNs a value of 0. So if you do #1 above, you'll simply get '0' in @text. The sp_helptext proc really just looks at the system tables. I've used sp_helptext for a quick and dirty in a query window. But you may be better using the system tables. Here's the query I generally use: select text from syscomments where id = (select id from sysobjects where xtype='p' and name = 'procname') I've hard-coded the xtype to 'p' for proc, in case you have a proc and table with the same name. I believe there's an object_id function that can be used to get the ID instead of my subselect on the sysobjects table, but I can never remember it (I had to look it up for this post) :) One last note. In SQL 2005 the system tables are "better" accessed though some new system views, such as sys.objects. I don't really know the difference, but if this is production quality code or you're just a pureist, you may want to investigate those. -ner
  12. Hmm... I'm guessing the problem from all the methods that don't work, is that they're operating off the window handle and having the window draw itself into the offscreen surface. Maybe the trick is to use the screen's handle itself so that it can pick up all the windows, including the tooltip. I'm sorry I've got no code or link to help, but thought the info might spark something else to try if you've run dry. -ners
  13. I've never seen a database treat them differently. Really? I've always seen BETWEEN treat things inclusively. So BETWEEN 1 and always picks up 1, 2, and 3. At least as far as SQL Server is concerned, there is no column that only holds a date. Everything has a time. Even if you insert '8/28/2007', SQL will tag on '12:00:00AM' - exactly midnight. If you have two rows on the same day, different times, then even MrPaul's query won't work. The best and easiest query I've used is one that uses the following day, as in: WHERE column >= @DateParam AND column < @DateParamPlusOneDay For example, to find all rows with a date on 8/28/2007 regardless of the time: WHERE column >= '8/28/2007' AND column < '8/29/2007' You *could* use BETWEEN, but the 2nd value in the expression would have to include the last possible second of time, such as: WHERE column BETWEEN '8/28/2007' AND '8/28/2007 11:59:59.999PM' -ners
  14. I've done exactly what you have Mondeo - differently named functions and a little more robust, but essentially the same concept. I was hoping it would have been alleviated with .net 2.0 and the inclusion of nullable types. They help, but you still need to translate between DBNull and null/Nothing. -ner
  15. Offhand, 200 sounds like a LOT of columns - just a general purpose bad smell. As far as limits, SQL Server has an 8k limit. Meaning, any one row of data in a table cannot exceed 8192 bytes, give or take. 200 fields at 8 bytes each is only 1600 bytes so you're ok there. -ner
  16. If nothing's changed, then I can't be much help. But if you've recently put code in a Form_Load event of a base form, that code will run when opening a form in the designer. I've found that most of the details in the resx aren't really useful and can safely be deleted. I use some 3rd party controls that LOVE to put data in the resx. As a test, you could try trimming that file just to see if it helps - then piecemeal it back in if that fixed it. That's in addition to PD's suggestion about the resx. You could also start looking in the InitializeComponent method created by the designer. Start commenting out code to see if there's something in there that's causing an issue. -ners
  17. In SQL Server, the UNION statement will do this for you. Simply do: SELECT man FROM table1 UNION SELECT man FROM table2 If you wanted all the names from both tables including duplicates you'd use "UNION ALL" instead of just "UNION" -ners
  18. Two keys elements are needed: "GROUP BY" and "MAX". For your simple query, here's the SQL: SELECT [Doc#], MAX(Date) AS [Date] FROM Table1 GROUP BY [Doc#] -ners
  19. Not a lot to go on, I'm afraid. If your program is pure .Net and you left the project options at default, then the compile options are "Any CPU" which means .Net will JIT compile for whatever OS the program is run on. If you chose to create a 32bit EXE then that will certainly have problems. Also, if you use any APIs through P/Invoke calls, they may be to blame. Did you create a setup for your program? I wonder if it would have detected the presence of the .Net Framework? You could also add more error checking, including an Application exception handler to catch errors more fully. -ner
  20. This is not super fun or easy to do, but possible. I can't release the code my company's developed, but it revolves around the API calls for SetWindowsHookEx, UnhookWindowsHookEx, CallNextHookEx and a few others to look for a window created with a class name of "#32770" - the magic value for a standard windows messagebox. The idea is this: 1. Call SetWindowsHookEx - this takes a param for a delegate that will get called on certain hooked events. 2. In the delegate, check the message type looking for HCBT_CREATEWND (value = 3). 3. Get the class name of the created window - compare to the magic value above. 4. Make sure to call CallNextHookEx (another API) 5. At some point (I can't recall when and not obvious from the code) much later, probably sometime before shutting down your application, call UnhookWindowsHookEx. -ner
  21. There should be a file called AssemblyInfo that is included in the default win exe project by visual studio. Open that up for those options and more. -ner
  22. Try using square brackets around column names. This works for table names as well. .firstNameTextBox.Text = guestdatarow!["[first name]"].tostring This may not be exactly right - I'm not familiar with the "!" syntax of VB.NET. I was mostly pointing out the change to using [first name] -ner
  23. marble, your idea sounds similar to the pattern of "nullable types" offered up my the Martin Fowler refactoring book. I tend to think of it as a "missing type," but the idea is the same. Introduce an inherited "Missing" object. Here's the idea: Define interface IMissing, which exposes one property: bool IsMissing. Create your Customer class, implemented the IMissing interface. The IsMissing property always returns false. Create your CustomerMissing class, inheriting from Customer. The IsMissing property always returns true. You provide "reasonable defaults" for any properties you want. Implies that you've marked the properties or methods as virtual in the base Customer class. So in code, a variable of type "Customer" would NEVER be null. This is generally enforced through a factory method that returns either Customer or CustomerMissing (which will also generally use the Singleton pattern). That's a lot of work for a simple "string" override - but sounds very similar in ideas. I think it might be useful to have "reasonable defaults" for some of the instance methods. Now for something almost but not completely different I had this conversation with a friend the other day - how nice would it be to allow calling "static" methods on an instance variable? The one that came to mind was string.IsNullOrEmpty(var) which I hate because of it's readability. Here's what you have now: if (string.IsNullOrEmpty(lastName)) {...} What I think would be infinitely better is: if (lastName.IsNullOrEmpty()) {...} The problem, of course, is that if "lastName" is null you'd get a null reference exception. Hence, the IsNullOrEmpty would either have to be special or a static method. Two problems with static: .Net doesn't allow static method calls on an instance variable AND a static method wouldn't know about the instance variable such as lastName above. Now here's the "AHA!" moment. DotNet has already imlemented this functionality for nullable types so I *KNOW* that it can be done! Take this example, which works: int? age = null; if (age.HasValue) { ... } Notice anything odd, or unexpected? You mean besides the fact that HasValue is a property being called on an instance variable that's null and you DO NOT get a null reference? Weird, but I *WANT* that behavior on my strings!!! That's all. -ner
  24. Most of the time, you want code and the user to not know about the AutoGenerated ID until after a record has been saved. A typical solution is to display "New" wherever the ID would normally be shown (such as a textbox with an "ID" label). After save, the "ID" field would update to show the real ID generated by the database. In our company, we set the seed in our DataTable to -1 with an increment of -1. That helps to differentiate a real ID from a "new ID." If you really want them in sync, there's the "guess" solution and the accurate method(s). I've listed these as I've seen them used before - there may well be other methods. 1. The "guess" method: When you enter "add" mode, run a query on the DB to get the "MAX(ID)" of the table/column you want and add 1. It's a guess because another user could insert a record after you've retrieved the MAX(ID) and then their record would be that ID and you'd get the next highest number. If you have a single user app, then this would probably be just fine. 2. The accurate method 1: Don't use autonumber columns - use a separate table that holds the "next ID" value. This changes your process to run some query that updates the table and returns the next ID for your app to use. The one drawback is that a user that cancels your transaction will generally leave that ID as "used" even though it wouldn't really be used. For example, you have a "NextCustomerNumber" table with the current value 124. The user chooses to add a customer so you query the table to get 125 and update the table to 125 - this increments the ID so the next person gets 126. Now the user cancels - maybe they didn't want to add the customer after all. Now the table will still have 125 and the next "Add Customer" will use 126, but there will be no Customer 125. 3. Allow saving an "empty" record. Here you'd allow saving a Customer with all NULL data when they click "Add Customer." The idea is that the save of a customer is always an update. If they choose to cancel the "Add Customer," you can still delete the dummy row you created. This would have lots of drawbacks. -ner
  25. You'll be wanting to look at the DataAdapter class. The DataAdapter is the piece that goes between the DataSet and the DataBase. The DataAdapter is meant to be easy to use, supporting the 4 main DB commands: SelectCommand, InsertCommand, UpdateCommand and DeleteCommand. There's even support for it to build all of those commands for you (such as basic SELECT, INSERT, etc. SQL statements) assuming you don't have any reserved words for table or column names. You'll end up calling an "Update" method on the DataAdapter, which will send the updates in your DataSet to the database (Access in your case). Each row in the DataSet has a "rowstate", such as "Unmodified", "Modified", "Deleted", etc. It's that rowstate that determines which command the DataAdapter will run. So if you've modified 1 row then the DataAdapter would call the UpdateCommand 1 time. After you call the Update method, you'll generally call AcceptChanges on the DataSet. It's probably worthwhile to find an article (or a set of them) or a book on the basic flow, to outline the "Why's" of the DataAdapter and DataSet.AcceptChanges and other things I'm leaving out. -ner
×
×
  • Create New...