public class ben:harrell

December 30, 2008

Beware of the “middleman”

Filed under: consulting — Tags: , — benjamin harrell @ 3:28 pm

I’ve consulted for many years and usually had good success going through recruiters, third parties, etc.  They normally provide a valuable service of “buffering” your corporate consulting pay essentially allowing you to get paid more frequently and also allowing a large company (such as an investment bank) to contract to several smaller corporations without dealing with each individually.  My warning comes from this relationship and the leverage that such a large entity has with both parties once they’ve established…errr entrenched themselves into the system.  Whenever the middleman has too much leverage he can actually screw both parties and squeeze out all sorts of profits through junk fees, delay of payment (to gain interest on the float), fee increases, etc.  Not only is it a complete scam that I wait on average 45 days to get paid for my work, this “middleman” now wants $2.50 out of every $100 I make!  We call that taxation where I come from and my only choice is to walk away but wait…that can’t be done because my “employer” only works with this 1 company so I’m forced to bendover and accept this increase.  Just remember this question when you get it:  Do you have a preferred vendor?  My new answer is NOT ZEROCHAOS…please let me know if any of you have had similar issues or if I’m way off base.

The following is an email from my “middleman”, ZeroChaos (can’t you just hear the sarcasm in the email?):

Dear Valued Partner-

Pursuant to the attached notification, the ZeroChaos administrative fee for all placements made at “Feral Wench” is now 2.50% for each billable hour. Continuing to provide Services on any ZeroChaos assignment at “Feral Wench” after December 19, 2008 will indicate Supplier’s acceptance of these terms. All invoiced time worked after 12/19/2008 will incur this updated administrative fee. Please direct any questions to the Workforce Support Services Team at 877-937-6242 Option 1 or service@zerochaos.com.

Best regards,

ZeroChaos Workforce Support Services


August 14, 2008

PSConfig.exe Beware!

Filed under: .NET, Team Foundation Server — Tags: — benjamin harrell @ 9:09 pm

I’m at the end of a 2 day TFS 2008 install marathon (yes, the one with the “fixed” installer) and I needed to move my WSS 3.0 config database (wss_config) to a new database which requires essentially creating a new wss_config database with the proper settings and I found an article about using PSConfig.exe to create/configure everything magically for you.  Now remember this is a Microsoft tool, recommended in MSDN and installed by WSS 3.0 so of course I trust that it does what it says.  Well, let me just say this

NEVER, EVER, EVER, EVER use this tool!

I ran it with the configdb command -create and oh yes I got my shiny new database but in the process it deleted my ENTIRE wwwroot folder.  I have no idea how or why but something is REALLY wrong deep down in this code.  If you wrote this code PLEASE feel free to contact me to discuss and I will gladly retract my statements but in the meantime save yourself the trouble.  I think STSAdm.exe might still do the job or perhaps you can do it from the Admin screens (not sure) but avoid this tool

June 8, 2008

SSIS Custom Source Component for EBCDIC

Well, it’s finally done!  Patrick and I finished version 1 of the EBCDIC Source Component which aids tremendously in the importing of EBCDIC (mainframe, IBM, old school stuff) data into SQL Server Integration Services.  We think this component will allow a number of shops to focus on getting the data right in their ETL solution within Integration Services rather than beating their head against an older data format that doesn’t always play well with others.

This component, named Lysine, works like most other Sources in SSIS so it should be easy to get started.  Currently, the component has the following features:

  • Several EBCDIC code pages supported
  • Intuitive Layout UI for rapid  development
  • Quick Preview to show you if your layout is correct
  • All major column types supported Redefines, Occurs, Occurs Depending, Packed (Comp-3), Zoned
  • Single Pass conversion for scalable performance
  • Export/Import of layout for team development

Please come check out the demo, browse the User Guide, try some Samples and let us know what you think!

September 18, 2007

SSIS Custom Component – ProvideComponentProperties vs ReInitializeMetadata

Filed under: .NET, Custom Source Component, Integration Servicees, SQL Server 2005, SSIS, Technology, database — benjamin harrell @ 9:47 am

 

I am currently working on a custom source component in SSIS that converts EBCDIC data to ASCII inline and one of the challenges I face is creating dynamic outputs and output columns based on the layout process of the source component.  Normally, when you want to additional outputs on your component you create them in by override ProvideComponentProperties like this:

public override void ProvideComponentProperties()
{
    // add the outputComponentMetaData.UsesDispositions = true;
   IDTSOutput90 output =     ComponentMetaData.OutputCollection.New();
   output.Name = “My New Output”;
   output.ExternalMetadataColumnCollection.IsUsed = true;

This works really well if all of your output information is available at design time (in the SSIS ui) but what happens if your dynamic outputs are determined at runtime?  ProvideComponentProperties is only called one time, when the component is added to designer surface.  In order to dynamically add outputs at a later point you must use ReInitializeMetaData which is called whenever Validate returns VS_NEEDSNEWMETADATA.

public override void ReinitializeMetaData()
{
   // add the output
   ComponentMetaData.UsesDispositions = true;
   IDTSOutput90 output = ComponentMetaData.OutputCollection.New();
   output.Name = “My New Output”;
   output.ExternalMetadataColumnCollection.IsUsed = true;
 }
 

Note that I have not shown the additional work of adding columns to either of these scenarios, you will need to add that code yourself. 

July 14, 2007

SSIS Row Limits and DefaultBufferMaxRows (Part 2)

Filed under: .NET, Custom Source Component, Integration Servicees, SSIS, database — benjamin harrell @ 10:44 am

I believe the mystery is solved and I’m sad to say that (as usual) it was something silly but crucial.  In a custom source component you must create a new PipelineBuffer in order to write your rows out.  SSIS has provided a way for us to let the engine know when we are done adding rows with a simple method “SetEndOfRowset”.  The name says it all and even the MSDN documentation is clear that you must call this.  In addition, your error logs if you don’t call this method will say something like:

The PrimeOutput method on <your component> returned success, but did not report an end of the rowset. 

 You would think that this error message would be enough to warn any developer that they were missing a key line of code but sadly that wasn’t the case.  In my case I had actually allocated 2 buffers, 1 for data rows and 1 for error rows.  I set a breakpoint on my SetEndOfRowset call and watched it execute so I just knew this wasn’t my problem.  But I forgot the second buffer!  So just a note to all you brave souls commanding bits on the SSIS battlefield.  Call SetEndOfRowset for EACH buffer you allocate. Good Luck! 

July 10, 2007

SSIS Row Limits and DefaultBufferMaxRows

Filed under: C#, Integration Servicees, SQL Server 2005, SSIS, Technology, database, errors — benjamin harrell @ 9:51 pm

I had an odd issue during some testing I was doing on a custom source component I’m writing for EBCDIC data conversion.  I first assumed that surely my code was at fault but the test just seemed to simple to be “my code”.  So here’s the scenario,  I have a file with 100,000 bytes of the number ‘1′ in EBCDIC.  I created a simple package to import the file as 1 byte rows into a Dataset Destination.  I was surprised when I executed the package and found that only 65,536 rows were processed.  Now if you have been around software for more than a week you probably recognize this magic number and unfortunately it triggers all sorts of theories about what could possibly be going wrong.  Well, I’m still trying to investigate the “why” and I’ll update this post and welcome comments if anyone has input but for now the solution to this oddity is to increase the DefaultBufferMaxRows to greater than your number of records.  This seems like a horrible workaround for a situation that should happen quite often so the hunt continues…

June 18, 2007

UPDATE: Cannot open user default database. Login failed. Login failed for user ‘UserName’. (Microsoft SQL Server, Error: 4064)

Filed under: SQL Server 2005, database, dba — benjamin harrell @ 10:24 am

 Thanks to Fritz Laurel for adding this in the comments section, after you gain access you may need to run this script to store the new default database for the Login you used.

ALTER LOGIN loginid
WITH DEFAULT_DATABASE = master
GO

March 1, 2007

Reporting Services 2005 Rotation and Orientation

Filed under: .NET, ASP.NET, C#, Reporting Services 2005, SQL Server 2005, Technology — benjamin harrell @ 4:54 pm

As many of you might have figured out by now Reporting Services 2005 doesn’t support rotating objects or multiple orientation (as in per sub report).  Depending on your situation there might still be an answer.  I was in a situation recently where I need certain pages of a report in landscape and some in portrait.  I was told that this is not possible out of the box in Reporting Services 2005 but have since found a workaround that might work for you.  Microsoft has done a great job with making SSRS an open architecture and the web services are a key part of this approach.  Behind the scenes of your Report Viewer control (in “remote” mode) it is actually making a request to the Render command of the SSRS Web Service.  So to pull of the rotation of a report I created a new web page with a web reference to the ReportService.  I then request the report in IMAGE format and store the byte[].  I create a new Bitmap object and stream in the byte[] so that I have full control over my newly created report Image in GDI.NET.  Bitmap supports a RotateFlip method that has just what we need and then I save the Bitmap to the Response.OutputStream object.  You are probably familiar with the concept of pointing an Image to an ASPX page that dynamically generates the bytes of the Image and this solution is no different.  Once you have an ASPX that can generate a rotated Image of the report then you treat it just like any other Image in the Report or on a WebForm.

This solution was adapted from Bryan Kelly’s post on Programmatically Printing RS 2000 Reports found HERE

The source code for the page is below:

 using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Drawing.Imaging;
using System.Drawing;
using System.Runtime.InteropServices; // For Marshal.Copy
using System.IO;
using System.Web.Services.Protocols;

public partial class ASR_ReportAsImage : System.Web.UI.Page
{
    ReportService.ReportingService rs;
    private byte[][] m_renderedReport;
    private System.Drawing.Graphics.EnumerateMetafileProc m_delegate = null;
    private System.IO.MemoryStream m_currentPageStream;
    private System.Drawing.Imaging.Metafile m_metafile = null;
    int m_numberOfPages;
 
    protected void Page_Load(object sender, EventArgs e)
    {
       
        rs = new ReportService.ReportingService();
        rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
        PrintReportAsImage();
    }

    public byte[][] RenderReport(string reportPath)
    {
        // Private variables for rendering
        string deviceInfo = null;
        string format = “IMAGE”;
        Byte[] firstPage = null;
        string encoding;
        string mimeType;
        ReportService.Warning[] warnings = null;
        ReportService.ParameterValue[] reportHistoryParameters = null;
        string[] streamIDs = null;
        Byte[][] pages = null;

        // Build device info based on the start page
        deviceInfo =
           String.Format(@”<DeviceInfo><OutputFormat>{0}</OutputFormat></DeviceInfo>”, “emf”);

        //Exectute the report and get page count.

        // Renders the first page of the report and returns streamIDs for
        // subsequent pages
        firstPage = rs.Render(
           reportPath,
           format,
           null,
           deviceInfo,
           null,
           null,
           null,
           out encoding,
           out mimeType,
           out reportHistoryParameters,
           out warnings,
           out streamIDs);
        // The total number of pages of the report is 1 + the streamIDs        
        m_numberOfPages = streamIDs.Length + 1;
        pages = new Byte[m_numberOfPages][];

        // The first page was already rendered
        pages[0] = firstPage;

        for (int pageIndex = 1; pageIndex < m_numberOfPages; pageIndex++)
        {
            // Build device info based on start page
            deviceInfo =
               String.Format(@”<DeviceInfo><OutputFormat>{0}</OutputFormat><StartPage>{1}</StartPage></DeviceInfo>”,
                 “emf”, pageIndex + 1);
            pages[pageIndex] = rs.Render(
               reportPath,
               format,
               null,
               deviceInfo,
               null,
               null,
               null,
               out encoding,
               out mimeType,
               out reportHistoryParameters,
               out warnings,
               out streamIDs);
        }

        return pages;
    }

    public bool PrintReportAsImage()
    {
        this.RenderedReport = this.RenderReport(“/ASR Prototype/ASR_TransactionOverview”);

        // Wait for the report to completely render.
        if (m_numberOfPages < 1)
            return false;

        for (int i = 0; i < m_renderedReport.Length; i++)
        {
            //write all of the pages to stream….

            System.IO.MemoryStream memstream = new System.IO.MemoryStream(m_renderedReport[i], false);
            System.Drawing.Bitmap oBitmap = new System.Drawing.Bitmap(memstream, true);
            //now rotate the bitmap 90 degrees
            oBitmap.RotateFlip(RotateFlipType.Rotate270FlipNone);
            //write it to the output stream
            Response.ContentType = “image/jpeg”;
            oBitmap.Save(Response.OutputStream, ImageFormat.Jpeg);

        }
        return true;
    }
 

    // Method to draw the current emf memory stream
    private void ReportDrawPage(Graphics g)
    {
        if (null == m_currentPageStream || 0 == m_currentPageStream.Length || null == m_metafile)
            return;
        lock (this)
        {
            // Set the metafile delegate.
            int width = m_metafile.Width;
            int height = m_metafile.Height;
            m_delegate = new Graphics.EnumerateMetafileProc(MetafileCallback);
            // Draw in the rectangle
            Point destPoint = new Point(0, 0);
            g.EnumerateMetafile(m_metafile, destPoint, m_delegate);
            // Clean up
            m_delegate = null;
        }
    }
    private bool MoveToPage(Int32 page)
    {
        // Check to make sure that the current page exists in
        // the array list
        if (null == this.RenderedReport[m_currentPrintingPage - 1])
            return false;
        // Set current page stream equal to the rendered page
        m_currentPageStream = new MemoryStream(this.RenderedReport[m_currentPrintingPage - 1]);
        // Set its postion to start.
        m_currentPageStream.Position = 0;
        // Initialize the metafile
        if (null != m_metafile)
        {
            m_metafile.Dispose();
            m_metafile = null;
        }
        // Load the metafile image for this page
        m_metafile = new Metafile((Stream)m_currentPageStream);
        return true;
    }
    private bool MetafileCallback(
       EmfPlusRecordType recordType,
       int flags,
       int dataSize,
       IntPtr data,
       PlayRecordCallback callbackData)
    {
        byte[] dataArray = null;
        // Dance around unmanaged code.
        if (data != IntPtr.Zero)
        {
            // Copy the unmanaged record to a managed byte buffer
            // that can be used by PlayRecord.
            dataArray = new byte[dataSize];
            Marshal.Copy(data, dataArray, 0, dataSize);
        }
        // play the record.     
        m_metafile.PlayRecord(recordType, flags, dataSize, dataArray);

        return true;
    }
    public byte[][] RenderedReport
    {
        get
        {
            return m_renderedReport;
        }
        set
        {
            m_renderedReport = value;
        }
    }

}

January 15, 2007

Cannot open user default database. Login failed. Login failed for user ‘UserName’. (Microsoft SQL Server, Error: 4064)

Filed under: SQL Server 2005, database, dba, errors — benjamin harrell @ 8:28 pm

Cannot open user default database. Login failed. Login failed for user ‘UserName’. (Microsoft SQL Server, Error: 4064)

This error bugged the crap out of me tonight and I saw all kinds of crazy answers usually involving some sort of SQLCMD -blah -blah…i think this maybe the problem with command line happy developers/dbas but to make a long story short the fix is EASY and you will kick yourself for not trying this. 

1.  click the options button if the options are not showing.

2.  click the connection properties tab if it is not active

3.  click on the Connect to database: dropdown

4.  type in the name of a database that still exists (ex. ‘master’)

5. connect!

 I heard all kinds of rants and raves about how atrocious it was that microsoft did this to us and I agree it does suck that SQL Server doesn’t do something about this automagically but what would you suggest it do?

October 7, 2006

Object Data Source Gotcha

Filed under: Uncategorized — benjamin harrell @ 10:37 pm

So you just created your super cool Business Object and you want to bind some control to it but when you add new data source you can’t see your object!!!

Not to worry, if you can’t see your object try this:

  1. cancel out of the dialog
  2. rebuild your project
  3. now re-add the datasource

Not sure how or why but, as usual, Visual Studio is caching objects :)

Older Posts »

Blog at WordPress.com.