tags:

views:

328

answers:

3

Hello. I'm trying to make tiny helper method for simplify routine operations But on the sample:

public static int getEntityId<Type, Entity>(String name) where Entity: class
{
    Type type = _db.GetTable<Entity>().SingleOrDefault(t => t.name == name);
    return 0;
}

i get error:

Error 1 'Entity' does not contain a definition for 'name' and no extension method 'name' accepting a first argument of type 'Entity' could be found (are you missing a using directive or an assembly reference?) c:\work\asutp_migration\asutp_migration\Program.cs 89 62 asutp_migration

Actually, this is expected error, but how to solve this? All tables/classes i will use with this method have "name" field/property.

UPD 1: according to advices i did this:

public partial class unit : IHasName
{
}

interface IHasName
{
    string name { get; }
    int id { get; }
}

public static int getEntityId<Type, Entity>(String name) where Entity: class, IHasName
{
    Type type = _db.GetTable<Entity>().SingleOrDefault(t => t.name == name);
    return (type == null) ? type.id : 0;
}

and with code:

int i = getEntityId<unit>("м");
Console.WriteLine(i);

i get exception:

Unhandled Exception: System.NotSupportedException: The mapping of interface member IHasName.name is not supported.

UPD 2: http://connect.microsoft.com/VisualStudio/feedback/details/344903/linq-to-sql-mapping-interface-member-not-supported-exception i can't believe. is it related to my issue?

UPD 3: yeah, seems it's VS issue: http://social.msdn.microsoft.com/Forums/en/linqtosql/thread/bc2fbbce-eb63-4735-9b2d-26b4ab8fe589

UPD 4:

public static int getEntityId<Type>(String name) where Type: class, IHasName
{
    Type type = _db.GetTable<Type>().SingleOrDefault(t => t.name.Equals(name));
    return (type != null) ? type.id : 0;
}

so this is a solution, thank you all :-)

+6  A: 

Well, you will need to make a generic constraint that specifies something more specific than class. For example, if you said where Entity : IHasName and IHasName defined a property name, then you would be all set.

mquander
That classes definitions are generated with builtin .dbml. Is it a good idea to custom them with additional interfaces?I've heard that reflection can help too, but i can't choose what solution is better.
zerkms
I think the builtin .dbml generation creates partial classes. You can go in the other file of the partial definition and modify the definition of the classes to `public partial class MyClass : IHasName`
Marcel Gosselin
+1 for the subtle and appropriate lolcats/lolcode reference (intentional or not).
Aaronaught
hmmmm, but interfaces cannot contain fields? interface IHasName { public string name; } Error 1 Interfaces cannot contain fields
zerkms
@zerkms : Interfaces can have properties. Define a property in the interface, then implement it in your class.
Rekreativc
@Rekreativc:only specified by "type name { acc/mut };" not just "type name;"
zerkms
A: 

I'll guess you're looking for something like:

public static int getEntityID<T>(string name) where T : Entity {
    T obj = _db.GetTable<T>().SingleOrDefault(t => t.name == name);
    return obj != null ? obj.id : 0;
}

here, Entity would be some base class (or interface)

public abstract class Entity { 
    public int id { get; set;}
    public string name { get; set; }
}

and your types would derive from that.

Jimmy
nope, Entity in my code is a tablename used for linq to sql.like _db.element_type...the "element_type" part is Entity. and it can changed within set of 3 or even more table names.
zerkms
@Jimmy, I think zerkms intended to use `Entity` as the generics classifier (Instead of `T,K` he's using `Type,Entity`)
Jim Schubert
@Jim, yep. I'm pretty new to c# so i don't know yet common meta-names :-(
zerkms
+1  A: 

Going off Jimmy's post and Zerk's answer:

public static int GetEntityID<T>(string name) 
    where T : IAnimal
{
    T obj = _db.GetTable<T>().SingleOrDefault(t => t.name == name);
    return obj != null ? obj.id : 0;
}

Edit2: Since you're new to this, here's an example of the above code usage:

/* You have a LinqToSql object of type Manatee */
int manateeId = MyClass.GetEntity<Manatee>("Jack");

It sounds like you're just trying to implement a repository pattern, which totally makes things easier. Here's an example of how to do it in LinqToSql: http://aspalliance.com/1672_Implementing_the_Repository_Pattern_with_LINQtoSQL.3

Once you learn how to do this, you can modify it to use for NHibernate or ADO.NET

Edit:

public interface IAnimal
{
  string name;
}

public Manatee : IAnimal
{
  public string name {get;set;}
  public int Age {get;set;}
  public strin Weight {get;set}
}
Jim Schubert
this gets the same error, because it's impossible statically to resolve whether K has name property or no
zerkms
@zerkms, I made a couple of edits to make this easier, and to show you how the Interface and the class that inherits the interface should be set up. Notice how the `name` property would be required in the Manatee class and any other class that inherits that interface. An interface just says "This class will definitely implement these properties and methods" This is why the Generic method you're trying to implement can use the Linq query `T obj = _db.GetTable<T>().SingleOrDefault(t => t.name == name);` and not worry about blowing up.
Jim Schubert
@Jim, how can you define interface with property? i get error about interfaces cannot contain fields :-S
zerkms