3

I am looking to get a list of the column names returned from a Model. Anyone know how this would be done, any help would be greatly appreciated.

Example Code:

var project = db.Projects.Single(p => p.ProjectID.Equals(Id));

This code would return the Projects object, how would I get a list of all the column names in this Model.

Thanks

Ben Scheirman
  • 40,531
  • 21
  • 102
  • 137
tsquillario
  • 997
  • 2
  • 8
  • 11

7 Answers7

15

This would be nice to have as an extension method:

public static class LinqExtensions
{
  public static ReadOnlyCollection<MetaDataMember> ColumnNames<TEntity> (this DataContext source)
  {
      return source.Mapping.MappingSource.GetModel (typeof (DataContext)).GetMetaType (typeof (TEntity)).DataMembers;
  }
}

example:

var columnNames = myDataContext.ColumnNames<Orders> ();
Todd Smith
  • 17,084
  • 11
  • 59
  • 78
  • this is a much better solution than using reflection. :) – IAbstract Sep 18 '10 at 22:39
  • You can also use the [PersistentDataMembers](http://msdn.microsoft.com/en-us/library/system.data.linq.mapping.metatype.persistentdatamembers.aspx) property in place of DataMembers to get only those properties that are persisted, rather than all properties on the object. – Jason S Oct 20 '11 at 04:04
  • Orders is The name of the table you want to column names for. – Todd Smith May 11 '12 at 21:24
6

Thanks guys, you got me started on the right track. I found my solution with the following code. I can then iterate through the DataMembers and pull out their individual properties such as name, type, etc.

var db = new GMPDataContext();
var columnNames = db.Mapping.MappingSource
                    .GetModel(typeof(GMPDataContext))
                    .GetMetaType(typeof(Project))
                    .DataMembers;
tsquillario
  • 997
  • 2
  • 8
  • 11
  • Awesome...I'll be using this. – IAbstract Sep 18 '10 at 22:39
  • I just translated to VB.NET and works. If anyone wants to use in VB: myData.Mapping.MappingSource().GetModel(GetType(NameOfYourDataContextObject)).GetMetaType(GetType(TableObjectFromDataContext).DataMembers – bernie2436 Dec 16 '11 at 18:24
3

Your Projects wrapper will have a set of properties each with a [Column] attribute. So just use reflection to enumerate the properties with that attribute.

Todd Smith
  • 17,084
  • 11
  • 59
  • 78
  • I don't understand why so many solutions use reflection. Scott Gu's solution to converting an IQueryable to DataTable uses reflection to build a schema from a table entity decorated with the TableAttribute. I'd rather "SELECT TOP 0 (field1, field2,...) FROM myTable" and execute the datareader as datatable. – IAbstract Sep 18 '10 at 22:37
2

Using Todd Smiths(+1) solution you get all properties (included entity sets, etc). To filter out all non-column properties this will do the trick:

var columnNames = db.ColumnNames<Orders>().Where(n => n.Member.GetCustomAttributes(typeof(System.Data.Linq.Mapping.ColumnAttribute), false).FirstOrDefault() != null).Select(n => n.Name);
Contra
  • 2,754
  • 4
  • 20
  • 18
  • nice addition! Just what I was looking for! – John Sep 02 '11 at 12:52
  • You can also use the [PersistentDataMembers](http://msdn.microsoft.com/en-us/library/system.data.linq.mapping.metatype.persistentdatamembers.aspx) property in place of DataMembers to get only those properties that are persisted, rather than all properties on the object. – Jason S Oct 20 '11 at 04:05
1

I am sorry, I don't have working experience with LINQ.

This is purely based on looking at MSDN.

DataContext has a Mapping property, which returns an instance of MetaModel.
MetaModel has GetMetaType, which takes a Type. In your case it could be typeof(Project).
GetMetaType returns a MetaType which has the GetDataMember method, which takes a MemberInfo parameter. You will have to use reflection on your Projects object to get the MemberInfo object.
The MetaDataMember instance returned by GetDataMember should have all the things, you need.

I hope I am somewhat in right direction (purely looking at MSDN & traversing)

Jason S
  • 1,361
  • 20
  • 24
shahkalpesh
  • 33,172
  • 3
  • 63
  • 88
  • Instead of `MetaType.GetDataMember(MemberInfo)`, you can use [`MetaType.PersistedDataMembers`](http://msdn.microsoft.com/en-us/library/system.data.linq.mapping.metatype.persistentdatamembers.aspx) which returns a collection of [`MetaDataMember`](http://msdn.microsoft.com/en-us/library/system.data.linq.mapping.metadatamember.aspx) objects which has the `Name`, `MappedName`, `IsPrimaryKey` properties etc that you need. Then you don't need Reflection. `PersistedDataMembers` returns only properties persisted, whereas `DataMembers` will give you all properties. – Jason S Oct 20 '11 at 04:35
0

Here an another way:

        public string[] GetColumnNames()
        {
            var propnames = GetPropertyNames(_context.Users);
            return propnames.ToArray();
        }

        static IEnumerable<string> GetPropertyNames<T>(IEnumerable<T> lst)
        {
            foreach (var pi in typeof(T).GetProperties())
            {
                yield return pi.Name;
            }
        }
Nalan Madheswaran
  • 10,136
  • 1
  • 57
  • 42
0

Your columns should be mapped as properties on your Project model. I'm not sure if you can get the underlying database structure when using LINQ to SQL. The entire point of LINQ to SQL is to abstract the database away.

Kyle West
  • 8,934
  • 13
  • 65
  • 97