title: C# abstract base class for common columns in LINQ
body: <p>This is what I have so far</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Data.Linq;
  using System.Data.Linq.Mapping;
  using System.Linq;
  using System.Text;
  
  namespace Firelight.Business
  {
      public interface IBaseEntity&lt;K&gt;
      {
          K Id { get; }
      }
  
      /// &lt;summary&gt;
      /// Base business database connection object, primary key is int
      /// &lt;/summary&gt;
      /// &lt;typeparam name="T"&gt;Table name&lt;/typeparam&gt;
      public abstract class BaseEntity&lt;T&gt; : BaseEntity&lt;T, Guid&gt; where T : class, IBaseEntity&lt;Guid&gt;
      {
      }
  
      /// &lt;summary&gt;
      /// Base business database connection object
      /// &lt;/summary&gt;
      /// &lt;typeparam name="T"&gt;Table name&lt;/typeparam&gt;
      /// &lt;typeparam name="K"&gt;Primary key type&lt;/typeparam&gt;
      public abstract class BaseEntity&lt;T,K&gt; : IBaseEntity&lt;K&gt; where T : class, IBaseEntity&lt;K&gt;
      {
          // Avoids having to declare IBaseConnection at partial class level
          [Column(Name = "Id", CanBeNull = false, IsPrimaryKey = true, IsDbGenerated = true)]
          public K Id { get; set; } // { return default(K); }
  
          public static Table&lt;T&gt; Table 
          {
              get { return LinqUtil.Context.GetTable&lt;T&gt;(); } 
          }
  
          public static T SearchById(K id)
          {
              return Table.Single&lt;T&gt;(t =&gt; t.Id.Equals(id));
          }
  
          public static void DeleteById(K id)
          {
              Table.DeleteOnSubmit(SearchById(id));
              LinqUtil.Context.SubmitChanges();
          }
      }
  }
  </code></pre>
  
  <p>My problem is that mapping doesn't work:</p>
  
  <blockquote>
    <p>Data member 'System.Guid [or System.Int32] Id' of type
    'X'
    is not part of the mapping for type
    'X'. Is the member above
    the root of an inheritance hierarchy?</p>
  </blockquote>
  
  <p>Before trying to map the attributes, I got this instead:</p>
  
  <blockquote>
    <p>Could not find key member 'Id' of key
    'Id' on type 'X'. The key may be wrong
    or the field or property on 'X' has
    changed names.</p>
  </blockquote>
  
  <p>I tried changing K to Guid and it works, but why? I don't see how generic-typing is an issue here</p>
  
  <p>I'm not entirely sure that I actually needed the Interface either, I don't really remember why I added it.</p>
  
  <p>So, the question would be: How can I make a class like this work? I want it so I can access a commonly named PK (Id), which always has the type K [which is Guid or Int32], and refactor basic functions like select and delete by Id</p>
  
  <p>Thanks!</p>
  
  <p>EDIT:</p>
  
  <p>this works</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Data.Linq;
  using System.Linq;
  
  namespace Firelight.Business
  {
      public interface IBaseEntity&lt;K&gt;
      {
          K Id { get; set; }
      }
  
      /// &lt;summary&gt;
      /// Base business database connection object
      /// &lt;/summary&gt;
      /// &lt;typeparam name="T"&gt;Table name&lt;/typeparam&gt;
      public abstract class BaseEntity&lt;T&gt; : IBaseEntity&lt;Guid&gt; where T : class, IBaseEntity&lt;Guid&gt;
      {
          // Avoids having to declare IBaseConnection at partial class level
          public Guid Id { get; set; }
  
          public static Table&lt;T&gt; Table 
          {
              get { return LinqUtil.Context.GetTable&lt;T&gt;(); } 
          }
  
          public static T SearchById(Guid id)
          {
              return Table.Single&lt;T&gt;(t =&gt; t.Id.Equals(id));
          }
  
          public static void DeleteById(Guid id)
          {
              Table.DeleteOnSubmit(SearchById(id));
              LinqUtil.Context.SubmitChanges();
          }
      }
  }
  </code></pre>
  
  <p>What I want would be basically the same, replacing Guid with K and making the class BaseEntity (so I can use the same class for Int32 and Guid PKs</p>