Sunday, March 6, 2011

DB Design: more tables vs less tables

Say I want to design a database for a community site with blogs, photos, forums etc., one way to do this is to single out the concept of a "post", as a blog entry, a blog comment, a photo, a photo comment, a forum post all can be thought as a post. So, I could potentially have one table named Post [PostID, PostType, Title, Body .... ], the PostType will tell what type of post it is.

Or I could design this whole thing with more tables, BlogPost, PhotoPost, ForumPost, and I'll leave Comment just it's own table with a CommentType column.

Or have a Post table for all types of post, but have a separate Comment table.

To be complete I'm using ADO.NET Entity Framework to implement my DAL.

Now the question what are some of the implications if I go with any route described above that will influence on my DB performance and manageability, middle tier design and code cleaness, EF performance etc.?

Thank you very much!

Ray.

From stackoverflow
  • Let me ask you this:

    What happens if two years from now you decide to add a 'music post' as a blog type? Do you have to create a new table for MusicPost, and then re-code your application to integrate it? Or would you rather log on to your blog admin panel, add a blog type in a drop-down box called 'Music', and be on your merry way?

    In this case, less tables!

    Kev : Wouldn't you have to add more specific code, e.g., to have a music player object embed in the page? But generally I agree.
    cLFlaVA : Potentially, yes. However, the modification you mention would still be far less work than revisiting the entire database structure.
  • The problem is similar to the question of how deep your hierarchy should be in an OO design.

    A simple approach in OO terms would be to have a base class Post and children for BlogPost, ForumPost and so on. Comment could either be a child of Post or its own hierarchy, depending on your requirements.

    Then how this is going to be mapped to DB tables is an entirely different question. This classical essay by Scott Ambler deals with the different mapping strategies and explains their advantages and disadvantages in a rather detailed way.

    Tony Andrews : Essays by Scott Ambler on database design always make me queasy - but I'm not down-voting you for it!
    Joachim Sauer : @Tony: really? is there a background to that feeling? I'd be interested in that.
  • Generally, life will be easier if you can have all the posts in one table:

    • less joins to perform
    • less tables to maintain
    • common attributes are not repeated between tables
    • code more generic

    However, you could run into some issues:

    • if each subtype has a lot of its own attributes, you could end up with many columns - maybe too many for your DBMS
    • if a subtype has an attribute (e.g. a stored picture) that is expensive for your DBMS to maintain even when unused, you might not want that column in all rows

    Should you run unto such an issue, you can create a new table just for the specific attributes of that post subtype - for example:

    create table posts (post_id number primary key, 
                        post_date date,
                        post_title ...); /* All the common attributes */
    
    create table photo_post (post_id references posts, photograph ...);
    

    In many cases, no such issues arise and a single table for all will suffice.

    I can't think of any merit in creating a distinct table for every subtype.

Convert String from ASCII to EBCDIC in Java?

Hello,

I need to write a 'simple' util to convert from ASCII to EBCDIC?

The Ascii is coming from Java, Web and going to an AS400. I've had a google around, can't seem to find a easy solution (maybe coz there isn't one :( ). I was hoping for an opensource util or paid for util that has already been written.

Like this maybe?

Converter.convertToAscii(String textFromAS400)
Converter.convertToEBCDIC(String textFromJava)

Thanks,

Scott

From stackoverflow
  • It should be fairly simple to write a map for the EBCDIC character set, and one for the ASCII character set, and in each return the character representation of the other. Then just loop over the string to translate, and look up each character in the map and append it to an output string.

    I don't know if there are any converter's publicly available, but it shouldn't take more than an hour or so to write one.

  • You can create one yoursef with this translation table.

    But here is a site that has a link to a Java example.

  • You should use either the Java character set Cp1047 (Java 5) or Cp500 (JDK 1.3+).

    Use the String constructor: String(byte[] bytes, [int offset, int length,] String enc)

  • JTOpen, IBM's open source version of their Java toolbox has a collection of classes to access AS/400 objects, including a FileReader and FileWriter to access native AS400 text files. That may be easier to use then writing your own conversion classes.

    From the JTOpen homepage:

    Here are just a few of the many i5/OS and OS/400 resources you can access using JTOpen:

    • Database -- JDBC (SQL) and record-level access (DDM)
    • Integrated File System
    • Program calls
    • Commands
    • Data queues
    • Data areas
    • Print/spool resources
    • Product and PTF information
    • Jobs and job logs
    • Messages, message queues, message files
    • Users and groups
    • User spaces
    • System values
    • System status
    scottyab : We are using the JTopen tool box and it is doing some of the convertion/mapping, it's just it seems to incorrectly map £,$,[ and ^
    Thorbjørn Ravn Andersen : Sounds like your AS/400 is incorrectly configured regarding its native tongue. If it is set up correctly jt400.jar will not require any other tweaking.
    Mike Wills : Yes, the conversion should happen basically automatically. If it isn't, something isn't setup right.
  • Please note that a String in Java holds text in Java's native encoding. When holding an ASCII or EBCDIC "string" in memory, prior to encoding as a String, you'll have it in a byte[].

    ASCII -> Java:   new String(bytes, "ASCII")
    EBCDIC -> Java:  new String(bytes, "Cp1047")
    Java -> ASCII:   string.getBytes("ASCII")
    Java -> EBCDIC:  string.getBytes("Cp1047")
    
    Thorbjørn Ravn Andersen : There are many EBCDIC code tables. It is very tedious to get right manually.
  • why would you write it if java already supports this charset?

Javascript Error thrown by AjaxToolKit in .NET only on some machines

We have a button that saves asynchronously using AjaxToolKit/C#/.NET. I'm getting this in my Error Console:

Error: [Exception... "'Sys.WebForms.PageRequestManagerServerErrorException: Sys.WebForms.PageRequestManagerServerErrorException:
An unknown error occurred while processing the request on the server. The status code returned from the server was: 500' when calling method:
[nsIDOMEventListener::handleEvent]"  nsresult: "0x8057001c (NS_ERROR_XPC_JS_THREW_JS_OBJECT)"  location: "<unknown>"  data: no]

The strangest thing about this is that it's only happening on some machines (but not all). Everyone in the office checked this out in FF 3.0.4 and IE 7, and the save works fine for most people. For the handful of people that it doesn't work for, it fails in both browsers.

Any ideas of where to start troubleshooting this?

  1. I'd say it was a server/code error, but it works for most people.
  2. I'd say it was a javascript error, but we're all using the same browser.
  3. I might even say it was an OS difference, but it happens to both XP and Vista users.
  4. User Permissions are the same for all of us

The application was working correctly until this weekend's update, where we updated a UserControl on the page. If I remove that control, the save works fine on all computers. When I add the control, we have the above situation where it fails on random computers.

Answer

Unfortunately, this was hard to track down due to the mysteriousness of how AjaxToolKit returns errors. The real culprit was that there was HTML in some of our fields in the UserControl. We added ValidateRequest="false" to the top of our page, and our problems disappeared.

The way we ultimately found the problem was to remove the UpdatePanel from around our Save button.

Sorry I didn't think of this sooner, because it was pretty straightforward from there. I'm giving Michael the accepted answer for his hard work and exhaustive troubleshooting list.

From stackoverflow
  • Things to check:

    1. Reboot (oldie but goodie, and doesn't always go without saying)
    2. OS version (you did this)
    3. Web browser (you did this)
    4. Web browser settings (you covered this by trying multiple browsers)
    5. Network connectivity and Hosts file rules
    6. User permissions (you covered this)
    7. Application permissions (you covered this)
    8. OS locale settings (control panel: Regional and Language Options)
    9. Try and capture more information.

    In this situation, I'd probably download a virgin browser to try to rule out browser settings. I'd throw Google Chrome onto a known good machine and a known bad machine to see what happens. If it works in both cases, then I'd look further at browser settings. I know that this isn't likely the case since it fails in both FF and IE, but IE this simple test could help provide a little more info nonetheless.

    It's a weird one. Since it affects both IE and FF, I'd also look at the connectivity angle, the hosts file, and permissions.

    Jon Smock : Good list - I'll edit my question to clarify some of these
    Jon Smock : Good call on the logs, searching now...
    Jon Smock : Can't find anything useful in IIS logs, Chrome didn't work on bad machine.
    Michael Haren : OK, since Chrome failed, we can ignore all the browser stuff, like cache, permissions, etc. What about the OS and network stuff? I assume you did a reboot, too...?
    Michael Haren : (Note that Chrome has to work on a good machine to be a valid test on the bad machine)
  • It is not the error of Ajax, Somewhere your code has error.remove Ajax and then check,u will come to know What is exact error.

    Ajit

Output library project XML to asp.net bin folder on build?

I have a visual studio 2005 solution which has a web application and a class library project. The web application has a reference to the library project. I'd like the library project's code documentation XML to output to the web application's bin folder, along with the library's DLL. I can't seem to find any easy way of doing this.

From stackoverflow
  • Post-build step, perhaps? A bit ugly, but I think it would work.

  • Use a post build event on the library project that will copy the Xml file to the web application's bin folder.

    For example you could use something like: copy $(TargetDir)\ $(SolutionDir)\

    This is untested so you'll prolly need to tweak it.

  • Here is the post-build command that worked:

    copy "$(TargetDir)$(TargetName).xml" "$(SolutionDir)MyWebProject1\bin\$(TargetName).xml"
    copy "$(TargetDir)$(TargetName).xml" "$(SolutionDir)MyWebProject2\bin\$(TargetName).xml"
    

    A couple of problems inherent with this solution:

    • The xml is always copied even if that website is not part of the current build... so the documentation can get out of sync with the the dll in the bin folder until the next time that web project is built.
    • If we add a new web project that refers to this library, we need to add another post-build command, rather than having this all happen automatically.

    I'm accepting this as a kludgy but workable solution... if anyone has a more elegant suggestion, please let me know!

    Thanks,

    Mike

Adobe Air - Using multiple SQLite databases at once

I have 2 SQLite databases, one downloaded from a server (server.db), and one used as storage on the client (client.db). I need to perform various sync queries on the client database, using data from the server database.

For example, I want to delete all rows in the client.db tRole table, and repopulate with all rows in the server.db tRole table.

Another example, I want to delete all rows in the client.db tFile table where the fileID is not in the server.db tFile table.

In SQL Server you can just prefix the table with the name of the database. Is there anyway to do this in SQLite using Adobe Air?

From stackoverflow
  • SQLite databases exist independently, so there's not way to do this from the database level.

    You will have to write your own code to do this.

  • It's possible to open multiple databases at once in Sqlite, but it's doubtful if can be done when working from Flex/AIR. In the command line client you run ATTACH DATABASE path/to/other.db AS otherDb and then you can refer to tables in that database as otherDb.tableName just as in MySQL or SQL Server.

    Tables in an attached database can be referred to using the syntax database-name.table-name.

    ATTACH DATABASE documentation at sqlite.org

  • I just looked at the AIR SQL API, and there's an attach method on SQLConnection it looks exactly what you need.

    I haven't tested this, but according to the documentation it should work:

    var connection : SQLConnection = new SQLConnection();
    
    connection.open(firstDbFile);
    connection.attach(secondDbFile, "otherDb");
    
    var statement : SQLStatement = new SQLStatement();
    
    statement.connection = connection;
    statement.text = "INSERT INTO main.myTable SELECT * FROM otherDb.myTable";
    statement.execute();
    

    There may be errors in that code snipplet, I haven't worked much with the AIR SQL API lately. Notice that the tables of the database opened with open are available using main.tableName, any attached database can be given any name at all (otherDb in the example above).

  • the code of floor2 can not use in flex3~~~ who can give me right code?

  • this code can be work,it is write of me: package lib.tools { import flash.utils.ByteArray;

    public class getConn
    {
     import flash.data.SQLConnection;
     import flash.data.SQLStatement;
     import flash.data.SQLResult;
     import flash.data.SQLMode; 
     import flash.events.SQLErrorEvent;
     import flash.events.SQLEvent;
     import flash.filesystem.File;
     import mx.core.UIComponent;
     import flash.data.SQLConnection;
    
     public var Conn:SQLConnection;
    

    /* 定义连接函数
    wirten by vivid msn:guanyangchen@126.com */

     public function getConn(database:Array)
     {  
                Conn=new SQLConnection();
                var Key:ByteArray=new ByteArray(); ;
                Key.writeUTFBytes("Some16ByteString"); 
                Conn.addEventListener(SQLErrorEvent.ERROR, createError);
                var dbFile:File =File.applicationDirectory.resolvePath(database[0]);
    
                Conn.open(dbFile);
                if(database.length>1){
                    for(var i:Number=1;i<database.length;i++){
                     var DBname:String=database[i]
                     Conn.attach(DBname.split("\.")[0],File.applicationDirectory.resolvePath(DBname));
                    }
                }
    

    /* 加密码的选项
    wirten by vivid msn:guanyangchen@126.com */

               Conn.open(dbFile, SQLMode.CREATE, false, 1024, Key); 
    
     }
    

    /* 出错返回信息函数
    wirten by vivid msn:guanyangchen@126.com */

        private function createError(event:SQLErrorEvent):void
                        {
                            trace("Error code:", event.error.details);
                            trace("Details:", event.error.message);
                        }
    

    /* 定义执行sql函数

    wirten by vivid msn:guanyangchen@126.com */

        public function Rs(sql:Array):Object{
            var stmt:SQLStatement = new SQLStatement();
         Conn.begin();
         stmt.sqlConnection = Conn;
    
    
         try{
             for(var i:String in sql){      
           stmt.text = sql[i]; 
                    stmt.execute();
             }
                Conn.commit();
            }catch (error:SQLErrorEvent){
           createError(error);
           Conn.rollback();
         };
    
            var result:Object =stmt.getResult();
            return result;
        }
    
    
    
    }
    

    }

Flex: Is there anyway to disable the textfield in the NumericStepper and force the user to change the value only by using the up/down buttons?

Probably not much more to elaborate on here - I'm using a NumericStepper control and I want the user to use the buttons only to change the value in the NS, not by typing into the control - I couldn't find a property to disable the text - does it exist?

If it doesn't, how would I subclass this thing to disable the text?

From stackoverflow
  • Ok - I think I got it - there is no property you can set but you can subclass the control and set:

    mx_internal::inputField.enabled = false;
    

    Although that sets up next question about what the hell mx_internal is...

  • mx_internal is a namespace. There's a good explanation of how it all works here:

    http://nondocs.blogspot.com/2007/04/mxcoremxinternal.html

  • In general, if you're using mx_internal, there's a decent chance that your app will break between flex versions.

Detecting multiple logged on users via win32

Using the standard win32 api, what's the best way to detect more than one user is logged on? I have an upgrade to our software product that can't be run when more than one user is logged in. (I know this is something to be avoided because of its annoyance factor, but the product is very complicated. You'll have to trust me when I say there really is no other solution.) Thanks.

From stackoverflow
  • In order to have more than one user logged in at once, Terminal Services or Fast User Switching must be enabled. Since Fast User Switching is implemented using Terminal Services, you first need to find out if the OS has it enabled. You can use GetVersionEx with an OSVERSIONINFOEX. Check for the VER_SUITE_SINGLEUSERTS and VER_SUITE_TERMINAL flags.

    If TS is enabled, you can use WTSEnumerateSessions to find out how many users are logged on. This only works if the "Terminal Services" service is started.

    If the machine doesn't support Terminal Services (or if the service isn't started), then you can only have one user logged on.

    Paul Betts : This is incorrect, with fast-user switching, > 1 user could be running processes at the same time.
    Roger Lipscombe : @Paul Betts: If you're using Fast user switching, then WTSEnumerateSessions will return all currently logged-on sessions, whether they're active or not.
  • This might be a roundabout way, but run down the process list and see who the process owners are.

  • Here's a solution that works on XP, Server 2003, Vista, and Server 2008. Note, this won't work on Windows 2000, because "LsaEnumerateLogonSessions" is not available on Windows 2000. This code is modified from a Delphi-PRAXIS post.

    To compile this, create a new VCL application with a TButton and a TMemo on the form. Then copy and paste this code and it should compile. I tested on XP and Vista and it works well. It will return interactive and remote users.

    unit main;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;
    
    const
      WTS_CURRENT_SERVER_HANDLE = 0;
    
    type
      PTOKEN_USER = ^TOKEN_USER;
      _TOKEN_USER = record
        User: TSidAndAttributes;
      end;
      TOKEN_USER = _TOKEN_USER;
    
      USHORT = word;
    
      _LSA_UNICODE_STRING = record
        Length: USHORT;
        MaximumLength: USHORT;
        Buffer: LPWSTR;
      end;
      LSA_UNICODE_STRING = _LSA_UNICODE_STRING;
    
      PLuid = ^LUID;
      _LUID = record
        LowPart: DWORD;
        HighPart: LongInt;
      end;
      LUID = _LUID;
    
      _SECURITY_LOGON_TYPE = (
        seltFiller0, seltFiller1,
        Interactive,
        Network,
        Batch,
        Service,
        Proxy,
        Unlock,
        NetworkCleartext,
        NewCredentials,
        RemoteInteractive,
        CachedInteractive,
        CachedRemoteInteractive);
      SECURITY_LOGON_TYPE = _SECURITY_LOGON_TYPE;
    
      PSECURITY_LOGON_SESSION_DATA = ^SECURITY_LOGON_SESSION_DATA;
      _SECURITY_LOGON_SESSION_DATA = record
        Size: ULONG;
        LogonId: LUID;
        UserName: LSA_UNICODE_STRING;
        LogonDomain: LSA_UNICODE_STRING;
        AuthenticationPackage: LSA_UNICODE_STRING;
        LogonType: SECURITY_LOGON_TYPE;
        Session: ULONG;
        Sid: PSID;
        LogonTime: LARGE_INTEGER;
        LogonServer: LSA_UNICODE_STRING;
        DnsDomainName: LSA_UNICODE_STRING;
        Upn: LSA_UNICODE_STRING;
      end;
      SECURITY_LOGON_SESSION_DATA = _SECURITY_LOGON_SESSION_DATA;
    
      _WTS_INFO_CLASS = (
        WTSInitialProgram,
        WTSApplicationName,
        WTSWorkingDirectory,
        WTSOEMId,
        WTSSessionId,
        WTSUserName,
        WTSWinStationName,
        WTSDomainName,
        WTSConnectState,
        WTSClientBuildNumber,
        WTSClientName,
        WTSClientDirectory,
        WTSClientProductId,
        WTSClientHardwareId,
        WTSClientAddress,
        WTSClientDisplay,
        WTSClientProtocolType);
      WTS_INFO_CLASS = _WTS_INFO_CLASS;
    
      _WTS_CONNECTSTATE_CLASS = (
        WTSActive,              // User logged on to WinStation
        WTSConnected,           // WinStation connected to client
        WTSConnectQuery,        // In the process of connecting to client
        WTSShadow,              // Shadowing another WinStation
        WTSDisconnected,        // WinStation logged on without client
        WTSIdle,                // Waiting for client to connect
        WTSListen,              // WinStation is listening for connection
        WTSReset,               // WinStation is being reset
        WTSDown,                // WinStation is down due to error
        WTSInit);               // WinStation in initialization
      WTS_CONNECTSTATE_CLASS = _WTS_CONNECTSTATE_CLASS;
    
      function LsaFreeReturnBuffer(Buffer: pointer): Integer; stdcall;
    
      function WTSGetActiveConsoleSessionId: DWORD; external 'Kernel32.dll';
    
      function LsaGetLogonSessionData(LogonId: PLUID;
         var ppLogonSessionData: PSECURITY_LOGON_SESSION_DATA): LongInt; stdcall;
         external 'Secur32.dll';
    
      function LsaNtStatusToWinError(Status: cardinal): ULONG; stdcall;
         external 'Advapi32.dll';
    
      function LsaEnumerateLogonSessions(Count: PULONG; List: PLUID): LongInt;
         stdcall; external 'Secur32.dll';
    
      function WTSQuerySessionInformationA(hServer: THandle; SessionId: DWORD;
         WTSInfoClass: WTS_INFO_CLASS; var pBuffer: Pointer;
         var pBytesReturned: DWORD): BOOL; stdcall; external 'Wtsapi32.dll';
    
    type
      TForm1 = class(TForm)
        Button1: TButton;
        Memo1: TMemo;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.dfm}
    
    function LsaFreeReturnBuffer; external 'secur32.dll' name 'LsaFreeReturnBuffer';
    
    procedure GetActiveUserNames(var slUserList : TStringList);
    var
       Count: cardinal;
       List: PLUID;
       sessionData: PSECURITY_LOGON_SESSION_DATA;
       i1: integer;
       SizeNeeded, SizeNeeded2: DWORD;
       OwnerName, DomainName: PChar;
       OwnerType: SID_NAME_USE;
       pBuffer: Pointer;
       pBytesreturned: DWord;
       sUser : string;
    begin
       //result:= '';
       //Listing LogOnSessions
       i1:= lsaNtStatusToWinError(LsaEnumerateLogonSessions(@Count, @List));
       try
          if i1 = 0 then
          begin
              i1:= -1;
              if Count > 0 then
              begin
                  repeat
                    inc(i1);
                    LsaGetLogonSessionData(List, sessionData);
                    //Checks if it is an interactive session
                    sUser := sessionData.UserName.Buffer;
                    if (sessionData.LogonType = Interactive)
                      or (sessionData.LogonType = RemoteInteractive)
                      or (sessionData.LogonType = CachedInteractive)
                      or (sessionData.LogonType = CachedRemoteInteractive) then
                    begin
                        //
                        SizeNeeded := MAX_PATH;
                        SizeNeeded2:= MAX_PATH;
                        GetMem(OwnerName, MAX_PATH);
                        GetMem(DomainName, MAX_PATH);
                        try
                        if LookupAccountSID(nil, sessionData.SID, OwnerName,
                                           SizeNeeded, DomainName,SizeNeeded2,
                                           OwnerType) then
                        begin
                          if OwnerType = 1 then  //This is a USER account SID (SidTypeUser=1)
                          begin
                            sUser := AnsiUpperCase(sessionData.LogonDomain.Buffer);
                            sUser := sUser + '\';
                            sUser := sUser + AnsiUpperCase(sessionData.UserName.Buffer);
                            slUserList.Add(sUser);
    //                          if sessionData.Session = WTSGetActiveConsoleSessionId then
    //                          begin
    //                            //Wenn Benutzer aktiv
    //                            try
    //                                if WTSQuerySessionInformationA
    //                                   (WTS_CURRENT_SERVER_HANDLE,
    //                                    sessionData.Session, WTSConnectState,
    //                                    pBuffer,
    //                                    pBytesreturned) then
    //                                begin
    //                                    if WTS_CONNECTSTATE_CLASS(pBuffer^) = WTSActive then
    //                                    begin
    //                                      //result:= sessionData.UserName.Buffer;
    //                                      slUserList.Add(sessionData.UserName.Buffer);
    //                                    end;
    //                                end;
    //                            finally
    //                              LSAFreeReturnBuffer(pBuffer);
    //                            end;
                              //end;
                          end;
                        end;
                        finally
                        FreeMem(OwnerName);
                        FreeMem(DomainName);
                        end;
                    end;
                    inc(List);
                    try
                        LSAFreeReturnBuffer(sessionData);
                    except
                    end;
                until (i1 = Count-1);// or (result <> '');
              end;
          end;
       finally
          LSAFreeReturnBuffer(List);
       end;
    end;
    
    procedure TForm1.Button1Click(Sender: TObject);
    var
      slUsers : TStringList;
    begin
      slUsers := TStringList.Create;
      slUsers.Duplicates := dupIgnore;
      slUsers.Sorted := True;
    
      try
        GetActiveUserNames(slUsers);
        Memo1.Lines.AddStrings(slUsers);
      finally
        FreeAndNil(slUsers)
      end;
    end;
    
    end.
    
    Mick : I should add that you can turn this code into an MSI DLL and use it as a windows installer (MSI) custom action. I have an example of how to do this with Delphi here: http://stackoverflow.com/questions/367365/how-do-i-write-custom-action-dll-for-use-in-an-msi.
    Mick : If you don't have Delphi, all of this code will compile and work just fine using the free Turbo Delphi. You can download that here: http://www.codegear.com/downloads/free/turbo

How do I get ASP.Net CompositeScript to cache in the browser?

I have been trying to improve the performance of a web page that references several separate javascript files. I found the new CompositeScript feature in .Net 3.5 SP1 that allows you to combine scripts at runtime through the ScriptManager and it works great to reduce the number of hits on our server at page load.

But the problem is that the combined script never caches on the client side. From everything I've read so far it should do that automatically. I don't have anything set to prevent it from caching (other scripts we reference that could not be combined cache fine, as do the ScriptResource.axd files). I even added the following to explicitly enable caching in the web.config:

<system.web.extensions>
 <scripting>
  <scriptResourceHandler enableCompression="true" enableCaching="true"/>
 </scripting>
</system.web.extensions>

But it doesn't seem to have an effect.

Has anyone seen this problem or have some suggestions on things I can try to fix it?

From stackoverflow
  • Is debug mode on anywhere? Make sure your webserver's Machine.Config has Retail="True"

    <configuration>
    <system.web>
    <deployment retail="true"/>
    </system.web>
    </configuration>
    

Why is my UserProperties collection empty ?

Hi,

I'm using the Outlook 2003 PIA and VS 2005 to access items in a public folder. The item.UserProperties collection always comes back empty, despite the items having several user defined fields.

If I add a property in code using UserProperties.Add, it is saved correctly with the item and is then available in the UserProperties next time the item is accessed. However, using MFCMapi to access the item I can see no difference between this new property and the existing user defined ones.

Any thoughts?

Thanks.

From stackoverflow
  • Hi,

    How are the items getting created in the public folders, using webdav? If they get created using webdav you can't access them using item.UserProperties method, because the blob value used by the outlook doesn't get populated correctly.

    Check this link for details.

    I am using a custom .Net Extended Mapi Wrapper to read this properties.

    But you can always use redemption or if you are using outlook 2007 , you can access them directly.

ASP.NET MVC Access Application Property from Model

my global.asax looks like this

Imports Castle.Windsor
Imports Castle.Windsor.Configuration.Interpreters

Public Class MvcApplication
    Inherits System.Web.HttpApplication
    Implements IContainerAccessor

    Private Shared IoC As IWindsorContainer

    Shared Sub RegisterRoutes(ByVal routes As RouteCollection)
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}")

        ' MapRoute takes the following parameters, in order:
        ' (1) Route name
        ' (2) URL with parameters
        ' (3) Parameter defaults
        routes.MapRoute( _
            "Default", _
            "{controller}/{action}/{id}", _
            New With {.controller = "Home", .action = "Index", .id = ""} _
        )

    End Sub

    Sub Application_Start()
        RegisterRoutes(RouteTable.Routes)
        IoC = New WindsorContainer(New XmlInterpreter)
    End Sub

    Public ReadOnly Property Container() As Castle.Windsor.IWindsorContainer Implements Castle.Windsor.IContainerAccessor.Container
        Get
            Return IoC
        End Get
    End Property
End Class

how do i access the Container property from within any Model Class? is there a class i can inherit from that gives me the "Application" property as in the view so i could to this

IoC = Application.Item("Container")...

From stackoverflow
  • You probably don't want your model objects knowing about your IoC container.

    But, for the sake of answering your question, you can access it like this:

    (C#)

    var container = ((IContainerAccessor)MvcApplication).Container;
    
    Paul : I want to agree 1000% that you don't want your model objects knowing about your IOC container. Everything they need from it should get passed to them when they get built.

Delphi(2006) Loop Help

So What I'm essentially trying to do is have something happen 70% of the time, another few things happen 10% of the time each if that makes sense but my app doesn't seem to do any of the actions I'm guessing I'm misunderstanding the loop syntax or something, anyway if anyone could take a look and maybe give me some advice

per1 := 70;
per2 := 77;
per3 := 84;
per4 := 91;
per5 := 100;
per6 := Random(2) + 1;
randomize;
RandPer:= Random(100);
randomize;
RandPer2 := Random(100);

 if RandPer2 <= 70 then begin
If RandPer <= per1 then begin
  Functiontest(1);
    end Else If RandPer <= per2 then begin
      Functiontest(3);
     end Else begin If RandPer <= per3 then begin
      Functiontest(5);
        end Else begin  If RandPer <= per4 then begin
        Functiontest(6);
          end Else begin If RandPer <= per5 then begin
          Functiontest(9);
          end;
         end;
        end;
      end;
From stackoverflow
  • You don't have any loop syntax, so that's certainly a possible source of your confusion.

    Do not call Randomize multiple times. It reinitializes the random seed each time you do, and that's based on the system clock. If your code runs faster than the clock advances, then your several calls to Randomize will actually reset the random seed to the same value it had before, resulting in repeated Random calls returning the same value.

    The help advises you to call Randomize just once at the start of your program. If you are writing a unit or component and you are not in charge of the whole program, then do not call Randomize at all. Instead, document that consumers of your code should call it themselves.

    If you are writing a DLL and not using run-time packages, then call Randomize in an initialization function that your DLL exports; consumers of your DLL won't have access to your DLL's copy of the Delphi run-time library.

    Also, if you want something to happen 70 percent of the time, then you should check whether your value is strictly less than 70. The possible return values of Random include zero; 70 percent of the results will be between 0 and 69 inclusive. Allowing 70 will actually make the event happen 71 percent of the time.

    Finally, your calculations of 10 percent of the time don't make sense to me. You have three events that will happen 7 percent of the time, and one that will happen 9 percent of the time. You can't have four events that each happen 10 percent of the time when you only have 30 percent remaining. Do you mean for each event's frequency to be measured independently of the others? If so, then do not link all your conditional tests together with else; Use completely a separate if statement for each one.

  • I just modified CharlesF code to do what you need. Hope CharlesF won't mind.

    begin
      randomize;
      for i := 0 to NumberOfTimesNeed do
      begin
        R :=  Random(100);
        case R of 
           0..69  : Functiontest(1); // this will fire 70% of NumberofTimes
           70..79 : Funciotntest(2); // 10 percent 
           80..89 : Funciotntest(3); // 10 percent 
           90..94 : Funciotntest(4); //  5 percent  
           // and so on ...
        end; 
    end;
    
    Charles Faiga : I like the modifications you made, the code is a lot more readable 
    Craig Stuntz : Don't call Randomize here; it's wrong. Do it in the initialization section.

Castle Windsor: How to programatically pass a list parameter to the container?

Is it possible to pass a list constructor parameter when resolving a type? I want to use a programmatic configuration if possible. I've been playing around with the Parameters method as shown below, but I've not yet stumbled upon the answer.

container.Register(
    Component
    .For<IDoSomething>()
    .ImplementedBy<DoSomething>()
    .Parameters(...)
);

The DoSomething class would look something like this

public class DoSomething : IDoSomething
{
    public DoSomething(List<string> listOfStrings) 
    {
        ...
    }
}
From stackoverflow
  • Aha!

    container.Register(
        Component
        .For<IDoSomething>()
        .ImplementedBy<DoSomething>()
        .Parameters(new { listOfStrings = someList })
    );
    
    Igor Brejc : -1 for not providing a real-life solution example...

Outlook VSTO AddIn for Meetings

We have created a VSTO addin for Outlook Meetings.

As part of this we trap on the SendEvent of the message on the FormRegionShowing event:

_apptEvents.Send += new Microsoft.Office.Interop.Outlook.ItemEvents_SendEventHandler(_apptEvents_Send);

The method _apptEvents_Send then tests on a couple of properties and exits where appropriate.

private void _apptEvents_Send(ref bool Cancel)
{
if (!_Qualified)
                    {
                        MessageBox.Show("Meeting has not been qualified", "Not Qualified Meeting", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        chkQualified.Focus();
                        Cancel = true;
                    }
}

The problem that we're having is that some users' messages get sent twice. Once when the meeting is sent and a second time when the user re-opens outlook.

I've looked for memory leaks, thinking that something might not be getting disposed of properly, and have added explicit object disposal on all finally calls to try and make sure resources are managed, but still getting the functionality incosistently across the organization. i.e. I never encountered the problem during development, nor other developers during testing. All users are up to date on framework (3.5 SP1) and Hotfixes for Outlook.

Does anyone have any ideas on what might be causing this?

Any ideas anyone might have would be greatly appreciated.

From stackoverflow
  • i'm no pro, but I've had trouble in the past when doing outlook automation due to people's send mail settings.

    For example, my mail only sends when i force a send/receive cycle. Most people have outlook to send immediately though and I remember some headaches when someone first asked for the really simple automation scripts.

    see if this is something that all the developers have in common and the user's may have set up differently.

  • Hi, Why do you use Microsoft.Office.Interop.Outlook.ApplicationEvents_10.Send Event Instead of adding the given handler over and over again.

    On startup method of your vsto addon, just add :

    ((MSOutlook.ApplicationEvents_10_Event)_OutlookApp).ItemSend += new Microsoft.Office.Interop.Outlook.ApplicationEvents_10_ItemSendEventHandler(Utils_ItemSend);
    
      void Utils_ItemSend(object Item, ref bool Cancel)
      {
            //Do your operation here.
      }
    

    Regards Kerem Kusmezer

Linq2Sql Many:Many question, How would you do this?

I know many:many isn't supported in Linq2Sql but I am working on a workaround

I am working with my little SO clone and I have a table with Questions and a table with Tags and a linking table QuestionTag so I have a classic many:many relationship between Questions and Tags.

To display the list of Questions on the front page I have this class I want to fill up from a Linq2Sql query

public class ListQuestion
{
   public int QuestionID { get; set; }
   public string Title{ get; set; }
   public IEnumerable<Tag> Tags { get; set; }
}


public IEnumerable<ListQuestion> GetQuestions()
{
   from q in Questions
   .................
   select new ListQuestion{ ... }
}

The problem is how should I fill up the Tag collection. I found out this isn't possible to do in 1 single query so I have divided this into 2 queries, 1 to get the questions and 1 to get the tags and later try to join them. I know many:many is supported in Entity framework so how do they do it? How would you do this? Any alternative approach? The query should of course be efficient.

From stackoverflow
  • This may work for your case;

    from q in Questions
    select new ListQuestion 
    { 
      Tags = q.QuestionTags.Select(qt => qt.Tag),
      QuestionId = q.ID,
      Title = q.Title
    }
    
    TT : It works. Thx a alot. I can't see how the actual query looks like. I would like to avoid that there is fired 1 query for every question to get the tags.
    Pure.Krome : Does this do TWO round trips to the DB? I've got the same exact question here: http://stackoverflow.com/questions/371279/how-can-i-reduce-the-number-of-db-round-trips-with-this-linq2sql
    yapiskan : No, there will be only one round trip to the DB.

Classes that have no member data

What do you do with classes that have no member data, only methods?

Do you make them static?

In my case it is an repository class that executes queries against the database. Maybe I got the repository pattern wrong... (It does implement an interface)

From stackoverflow
  • It depends. Most of the time it might be possible to make the class static, but sometimes you need to pass an instance of it around. Sounds like you might be having this situation. In this case perhaps you should consider a Singleton pattern, since more than 1 instance of the class is not likely to be needed?

  • If it implements an interface, and gets passed around as that interface, then you can't make the members (or the class) static. The interface aspect means that although an instance won't have any actual fields, it still contains valuable information - its type.

    You might want to make it a singleton, but there's no particular need to.

  • Inherit from an Interface mean that you cannot use static. Simply create a class and instantiate it.

  • Why won't you make a database wrapper class, that maintains the connection to database opened/closed. Moreover, it can also open it automatically if new query is sent. You can include the functions your class has, running them right on the inner pointer to the database.

    I guess this is the best database management pattern. If you use it, you should make a Factory method that returns the object of this class initialized on some specific database. Then you pass that object around.

    Or if you are lazy and sure that you will need only 1 database, make it a singleton.

Ignoring accented letters in string comparison

I need to compare 2 strings in C# and treat accented letters the same as non-accented letters. For example:

string s1 = "hello";
string s2 = "héllo";

s1.Equals(s2, StringComparison.InvariantCultureIgnoreCase);
s1.Equals(s2, StringComparison.OrdinalIgnoreCase);

These 2 strings need to be the same (as far as my application is concerned), but both of these statements evaluate to false. Is there a way in C# to do this?

From stackoverflow
  • try this overload on the String.Compare Method.

    String.Compare Method (String, String, Boolean, CultureInfo)

    It produces a int value based on the compare operations including cultureinfo. the example in the page compares "Change" in en-US and en-CZ. CH in en-CZ is a single "letter".

    example from the link

    using System;
    using System.Globalization;
    
    class Sample {
        public static void Main() {
        String str1 = "change";
        String str2 = "dollar";
        String relation = null;
    
        relation = symbol( String.Compare(str1, str2, false, new CultureInfo("en-US")) );
        Console.WriteLine("For en-US: {0} {1} {2}", str1, relation, str2);
    
        relation = symbol( String.Compare(str1, str2, false, new CultureInfo("cs-CZ")) );
        Console.WriteLine("For cs-CZ: {0} {1} {2}", str1, relation, str2);
        }
    
        private static String symbol(int r) {
        String s = "=";
        if      (r < 0) s = "<";
        else if (r > 0) s = ">";
        return s;
        }
    }
    /*
    This example produces the following results.
    For en-US: change < dollar
    For cs-CZ: change > dollar
    */
    

    therefor for accented languages you will need to get the culture then test the strings based on that.

    http://msdn.microsoft.com/en-us/library/hyxc48dt.aspx

  • The following method CompareIgnoreAccents(...) works on your example data. Here is the article where I got my background information: http://www.codeproject.com/KB/cs/EncodingAccents.aspx

    private static bool CompareIgnoreAccents(string s1, string s2)
    {
        return string.Compare(
            RemoveAccents(s1), RemoveAccents(s2), StringComparison.InvariantCultureIgnoreCase) == 0;
    }
    
    private static string RemoveAccents(string s)
    {
        Encoding destEncoding = Encoding.GetEncoding("iso-8859-8");
    
        return destEncoding.GetString(
            Encoding.Convert(Encoding.UTF8, destEncoding, Encoding.UTF8.GetBytes(s)));
    }
    

    I think an extension method would be better:

    public static string RemoveAccents(this string s)
    {
        Encoding destEncoding = Encoding.GetEncoding("iso-8859-8");
    
        return destEncoding.GetString(
            Encoding.Convert(Encoding.UTF8, destEncoding, Encoding.UTF8.GetBytes(s)));
    }
    

    Then the use would be this:

    if(string.Compare(s1.RemoveAccents(), s2.RemoveAccents(), true) == 0) {
       ...
    
  • Write a method normalize(String s) that takes in a string and turns accented letters into non accented one. Then instead of comparing string x to string y, compare normalize(string x) to normalize(string y).

  • Here's a function that strips diacritics from a string:

    static string RemoveDiacritics(string sIn)
    {
      string sFormD = sIn.Normalize(NormalizationForm.FormD);
      StringBuilder sb = new StringBuilder();
    
      foreach (char ch in sFormD)
      {
        UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(ch);
        if (uc != UnicodeCategory.NonSpacingMark)
        {
          sb.Append(ch);
        }
      }
    
      return (sb.ToString().Normalize(NormalizationForm.FormC));
    }
    

    More details here.

    The principle is that is it turns 'é' into 2 successive chars 'e', acute. It then iterates through the chars and skips the diacritics.

    "héllo" becomes "he<acute>llo", which in turn becomes "hello".

    Debug.Assert("hello"==RemoveDiacritics("héllo"));
    

    This line doesn't assert, which is what you want.

Add LDAP entry to Active Directory via ext/ldap

Using ext/ldap I'm trying to add entries to an Active Directory. As long as I only use one single structural objectClass everything works as expected, but as soon as I try to add an entry with a second auxiliary objectClass, the server reports an error:

Server is unwilling to perform; 00002040: SvcErr: DSID-030F0AA0, problem 5003 (WILL_NOT_PERFORM), data 0

The following code works:

ldap_add($ldap, 'OU=Test,OU=Test,DC=domain,DC=example,DC=local', array(
    'ou' => 'Test',
    'objectClass' => 'organizationalUnit',
    'l' => 'location'
));

This doesn't:

ldap_add($ldap, 'OU=Test,OU=Test,DC=domain,DC=example,DC=local', array(
    'ou' => 'Test',
    'associatedDomain' => 'domain',
    'objectClass' => array('organizationalUnit', 'domainRelatedObject'),
    'l' => 'location'
));

The same happens if I try to add an auxiliary objectClass to an existing entry:

ldap_mod_add($ldap, 'OU=Test,OU=Test,DC=domain,DC=example,DC=local', array(
    'associatedDomain' => 'domain',
    'objectClass' => 'domainRelatedObject'
));

The corresponding error message is essentially the same

Server is unwilling to perform; 00002040: SvcErr: DSID-030508F8, problem 5003 (WILL_NOT_PERFORM), data 0

As all other updating and adding operations work, I think the problem must be related to the objectClass attribute.

As I've not enough experience with Active Directories (I'm used to OpenLDAP): Are there any known issues with objectClasses in Active Directory? Am I missing something here? Are there any restrictions that disallow adding e.g. domainRelatedObject to an organizationalUnit? What the heck 's going on here ;-)?

Just in case you're wondering: the domainRelatedObject is present in the Active Directory schema.

From stackoverflow
  • You may not have permission to set the objectClass attribute. See whether you can attach the auxiliary class after creation, through ADSI Edit. If you can't, fix the permissions first (check the Properties tab in the Advanced view of Security settings)

    I could attach this specific class right now, onto a organizationalUnit object, as a domain admin; so in principle, this is possible.

    Stefan Gehrig : Neither ADSI Edit nor ldp.exe will allow me to add the auxiliary class. ADSI Edit says "Die angegebene Methode wird nicht unterstützt" ("The specified method is not supported"). ldp.exe says: "Error: Modify: Ausführung verweigert. [...]
    Stefan Gehrig : [...] <53> Server error: 00002040: SvcErr: DSID-030F0AA0, problem 5003 (WILL_NOT_PERFORM), data 0" This is the same even if I'm authenticated as a Domain Admin.
    Martin v. Löwis : Hmm. What's the server? I was using W2k3SP2, and it worked fine.
  • I just found that, in order to add dynamic (per-instance) aux classes, the forest functional level of the domain must be 2003.

    Stefan Gehrig : Hi Martin! Thanks a lot - that was the problem... I don't dare to think about the time I wasted on this one on the PHP side ;-)

how can I find the location of the solution/project on my harddrive in Visual Studio?

I want to know where the solution/project is stored on my hard drive.

I would have thought right clicking on the project from within Visual Studio would have the information on where it is stored on my hard drive, but it doesn't.

From stackoverflow
  • One way is to select the project in the solution explorer and then click File / Save As or press F4 and view the 'Project Folder' property.

  • Click on the project itself in the solution explorer and in the properties window it lists the project folder.

    Only works if you've actually saved the project though. I.e. newly created projects don't have a location.

  • Start up Visual Studio and go to Tools->Options.

    In the dialog box that opens, make sure to check the box that displays "Show All Settings."

    From there, you should find a setting called "Projects and Solutions" which will have the list of default locations for projects, templates, etc.

  • When you have loaded you project in Visual Studio select the solution in the Solution explorer window and then select Properties window. You will see "Path" in the Properties window which points to the actual file.

  • Open one of the files in your Solution and hover over the tab in the code window. The full path will show up in a tooltip.

    You can also go to Window | Windows... which shows you full path to all open files.

c++ deduction of "non type pointer to function" class template parameters

Consider a template class like:

template<typename ReturnType, ReturnType Fn()>
class Proxy
{
    void run()
    {
     ReturnType ret = Fn();
     // ... do something ...
    }
};

// and a functions
int fn1() { return 5; }
float fn2() { return 5; }

This can be instantiated by using:

Proxy<int, &fn1> p1;

But explicitly declaring the return value type seems needless. What I am trying to achieve is something like:

 someProxyInstantation<&fn1> p1;
 someProxyInstantation<&fn2> p2;

Unfortunately, I'm no c++ expect and this seems like a hidden corner of the language (at least for me).

If I could just get from the pointer to the function to its type - something like: std::tr1::result_of<&fn>::type // Error 1 error C2923: 'std::tr1::result_of' : 'fn1' is not a valid template type argument for parameter '_Fty'

the error makes sense since the parameter is not a "type" at all

C++0x has the decltype(&fn1) but that is years away.

Any way of doing this in C++03 (+ tr1)?

Restrictions: - I don't want to pass the functor, f1 and f2 have to remain global functions that have a return value (can't move it to parameter).)

From stackoverflow
  • This isn't possible in C++03. If you want to pass a function pointer as a non-type parameter, the compiler has to know the type of the parameter. So you have to provide the missing pieces (in this case, the return type). You can give the proxy the function pointer as a value at runtime, and provide it with the type of it as the only argument. Then you could write a generator function for you that does this job:

    template<typename T>
    Proxy<T> make_proxy(T t) { return Proxy<T>(t); }
    

    Sadly, in current C++, you still have to give it the type in order to assign to a automatic variable:

    Proxy<int(*)()> p = make_proxy(&fn1);
    

    You can't use auto p = make_proxy(&fn1); yet. Note that if you want to use a function type on the left side, you have to change the generator function to provide not a function pointer type:

    template<typename T>
    Proxy<typename boost::remove_pointer<T>::type> make_proxy(T t) { 
        return Proxy<typename boost::remove_pointer<T>::type>(t); 
    }
    

    Now you can do

    Proxy<int()> p = make_proxy(&fn1);
    

    using the proxy, you can now just do

    doSomething(make_proxy(&fn1));
    

    And if doSomething is templated or otherwise polymorphic, it will not require you to know the exact type of the function.

    Hrvoje Prgeša : Until c++0x this will have to do.

How to design and implement a simple WCF service relay?

We are in the process of designing a simple service-oriented architecture using WCF as the implementation framework. There are a handful of services that a few applications use. These services are mostly used internally, so a basic authentication and authorization scheme (such as Windows-based) is enough.

We want, however, expose some of the services to some business partners. The set of services they have access to depend on the contract. Kind of a standard architecture.

I think we can implement a service gateway which authenticates the requests and relays them to the correct internal service endpoint (this resembles simple ESB), so we can centralize the authentication/authorization code and expose one single endpoint to the world. I looked at some available ESB toolkits, but they seem way too complex for this purpose. We do not need to integrate a lot of different services, but just to expose some of them to the Internet.

How can I design and implement such a relay/router in WCF, keeping it very simple? I have read Inside Windows Communication Foundation, which is a good book, but I'm still not confident enough on how to begin.

From stackoverflow
  • I have done something very similar to this. What you can do is expose an endpoint with a single operation.

    That operation would look something like

    [OperationContract(Namespace="www.fu.com", Action="*")]
    void CallThis(Message msg);
    

    Have your clients use a proxy that is intended for the service they intended to calling the operation they want. Then have them change the configuration to point to your endpoint/service. The "CallThis" method will accept any operation, regardless of its signature. The Message parameter is the WCF Message.

    Do what you need to do to determine where things are supposed to go, but you will need to change the "To" to go to your internal endpoint.

    I actually have a full implementation of this, so if you have questions, let me know.

    Joe.

    Dario Solera : Thank you, I'm exploring this option. The problem is that I'm not sure how to return the response generated by the internal service to the external requester.
    Joseph DeCarlo : Good point. My implmentation uses one way messages, so I don't have to deal with that. Using the Action="*" attribute forces this call to be higher in the WCF stack. So no serialization of types happens during your call.You should be able putting a return type of Message and it should work.
    tomasr : Dario: You should still be able to use a catch all handler like the above and return a Message instance; it doesn't need to be a one way operation.
  • It seems it is sufficient to build an interface as follows:

    [OperationContract(Action="*", ReplyAction="*")]
    Message CallThis(Message msg);
    

    I also found this post useful for implementing the CallThis method by "fiddling" with Message objects. A basic implementation of the CallThis method follows:

    public Message CallThis(Message message) {
        MessageBuffer buffer = message.CreateBufferedCopy(524288);
        Message output = buffer.CreateMessage();
        output.Headers.To = <INTERNAL_SERVICE_URI>;
    
        BasicHttpBinding binding = new BasicHttpBinding();
        IChannelFactory<IRequestChannel> factory = binding.BuildChannelFactory<IRequestChannel>(<INTERNAL_SERVICE_URI>);
        factory.Open();
    
        IRequestChannel channel = factory.CreateChannel(new EndpointAddress(<INTERNAL_SERVICE_URI>));
        channel.Open();
    
        Message result = channel.Request(output);
    
        message.Close();
        output.Close();
        factory.Close();
        channel.Close();
    
        return result;
    }
    

    Adding authentication and authorization should be quite straightforward.

  • Check out this SO question where one of the responses suggests .NET 4's RoutingService. Very nice addition to WCF.