Use a TTF file as an embedded font in your C# application

Use a TTF file as an embedded font in your C# application

I had a problem with an application missing a font when deployed remotely. The solution was to get the TTF (font file) as an embedded resource in my project, and load that rather than loading it from Windows Fonts.

 

First, get your TTF file imported to your project, and set its Build Action to the Embedded Resource option.

Next, let’s create an EmbeddedFonts class that will load this TTF embedded resource for us:

using System.Reflection;
using System.Drawing;
using System.Drawing.Text;
using System.IO;
using System.Runtime.InteropServices;
using System;

public static class EmbeddedFonts
{
    // Adding a private font (Win2000 and later)
    [DllImport("gdi32.dll", ExactSpelling = true)]
    private static extern IntPtr AddFontMemResourceEx(byte[] pbFont, int cbFont, IntPtr pdv, out uint pcFonts);

    // Cleanup of a private font (Win2000 and later)
    [DllImport("gdi32.dll", ExactSpelling = true)]
    internal static extern bool RemoveFontMemResourceEx(IntPtr fh);

    // Some private holders of font information we are loading
    static private IntPtr m_fh = IntPtr.Zero;
    static private PrivateFontCollection m_pfc = null;

    /////////////////////////////////////
    //
    // The GetSpecialFont procedure takes a size and
    // create a font of that size using the hardcoded
    // special font name it knows about.
    //
    /////////////////////////////////////
    public static Font GetSpecialFont(float size)
    {

        Font fnt = null;

        if (null == m_pfc)
        {

            // First load the font as a memory stream
            Stream stmFont = Assembly.GetExecutingAssembly().GetManifestResourceStream(
                                    "StyleMyImage.MVC.fontsCustom.Tahoma.ttf");

            if (null != stmFont)
            {
                // GDI+ wants a pointer to memory, GDI wants the memory.
                // We will make them both happy.

                // First read the font into a buffer
                byte[] rgbyt = new Byte[stmFont.Length];
                stmFont.Read(rgbyt, 0, rgbyt.Length);

                // Then do the unmanaged font (Windows 2000 and later)
                // The reason this works is that GDI+ will create a font object for
                // controls like the RichTextBox and this call will make sure that GDI
                // recognizes the font name, later.
                uint cFonts;
                AddFontMemResourceEx(rgbyt, rgbyt.Length, IntPtr.Zero, out cFonts);

                // Now do the managed font
                IntPtr pbyt = Marshal.AllocCoTaskMem(rgbyt.Length);
                if (null != pbyt)
                {
                    Marshal.Copy(rgbyt, 0, pbyt, rgbyt.Length);
                    m_pfc = new PrivateFontCollection();
                    m_pfc.AddMemoryFont(pbyt, rgbyt.Length);
                    Marshal.FreeCoTaskMem(pbyt);
                }
            }
        }

        if (m_pfc.Families.Length > 0)
        {
            fnt = new Font(m_pfc.Families[0], size);
        }

        return fnt;
    }
}

 

That’s everything! Lastly, in our application code we can get a handle to our Font object with Font Size = 14 like this:

Font font = EmbeddedFonts.GetSpecialFont(14);

 

Using SqlBulkCopy for Bulk Insert of records in C#

Using SqlBulkCopy for Bulk Insert of records in C#want

You want to insert a large number of rows to a database table, and you want it to be fast (and simple). Use SqlBulkCopy.

 

Simply create a DataTable with columns that match your table. Then populate the DataTable object with your records, and call a SqlBulkCopy WriteToServer.

DataTable table = new DataTable("MyTableName");
table.Columns.Add(new DataColumn("Id", typeof(int)));
table.Columns.Add(new DataColumn("Name", typeof(string)));
table.Columns.Add(new DataColumn("City", typeof(string)));

foreach(var person in persons)
{
	// NOTE: If Id is identity, then the value set here is ignored
	table.Rows.Add(person.Id, person.Name, person.City);
}

SqlConnection sqlConnection = new SqlConnection(...);

using (SqlBulkCopy bulkCopy = new SqlBulkCopy(sqlConnection))
{
	bulkCopy.BatchSize = 100;
	bulkCopy.BulkCopyTimeout = 600; // seconds
	bulkCopy.DestinationTableName = "[DBO].[MyTableName]";
	bulkCopy.WriteToServer(table);
}

 

Any errors that I’ve observed result in an exception being thrown, so be sure to add a try catch block around wherever you want to handle exceptions.