How to create a common method from two identical but different methods?

I have two similar methods that basically do the same thing with different objects only. What is the best way to make this a common method, if possible?

Two objects:

public class StoreObject { int Key; string Address; string Country; int Latitude; int Longitude; } public class ProjectObject { int ProjectKey; string Address; string Description; } 

Two methods that I potentially want to do in general:

 public StoreObject GetStoreByKey(int key) { using (DBEntities dbe = new DBEntities()) { StoreObject so = new StoreObject(); var storeObject = (from s in dbe.StoreTables where s.Key == key select s).First(); so.Key = storeObject.key; so.Address = storeObject.address; so.Country = storeObject.country; so.Latitude = storeObject.latitude; so.Longitude = storeObject.longitude; return so; } } public ProjectObject GetProjectByKey(int projectKey) { using (DBEntities dbe = new DBEntities()) { ProjectObject po = new ProjectObject(); var projectObject = (from p in dbe.ProjectTables where p.ProjectKey == projectKey select p).First(); po.Key = projectObject.p_key; po.Address = projectObject.p_address; po.Description = projectObject.p_description; return po; } } 

I should note that:
- I have no control over what the table fields are called (for example, p_description).
For example, a StoreTable in a database may have other properties (for example, phone, zip code, etc.), but I'm only interested in showing what I showed in the code.
- The same goes for ProjectTable.

+7
source share
4 answers

Well, the tricky part is that your objects have different properties, so using generics to populate different properties within the same method will not be worth it. But you can return the whole object, and then just use the properties you are interested in.

 public T GetEntityByKey<T>(int key) { using (DBEntities dbe = new DBEntities()) { return = dbe.StoreTables.Set<T>.Find(new object[] {key}); } } 

And use it

 StoreObject so = GetEntityByKey<StoreObject>(123); if(so != null) { int lat = so.Latitude; } 
+3
source

You can really abstract away from the return type and force the using factor, but for the rest you need either a switch on the requested type or a reflection for passing in the fields to extract as parameters and query the database for use.

The first would be bad practice and lead little to the equation, and the second would be expensive and could get confused.

This is not a good candidate for generics if you have a lot of such similar methods, in which case I would go for an approach to thinking.

NTN

Women.

+2
source

It is very unlikely that this is your whole โ€œunit of workโ€, and so using the new DBEntities() context in each of these methods is probably the root of your problem here.

Creating a Repository class that includes an instance of the DBEntities class for a single web request (or any other request unit that you have in your application) and that has these methods in it will be the best approach to eliminating duplicate code here. The using() scope is outside the scope of these methods and hopefully is bound to your web request or other unit of time.

As an option, instead of creating a new class, you can also extend the partial DBEntities class to include such methods (provided that it is the generated code).

+2
source

You essentially have two different functions in each method:

  • Property Request
  • Match this object to another type

The first part was reviewed by Steve Mallory.

For the second part, you can use the mapper framework to handle copy values โ€‹โ€‹from one instance to another. Since the names of each type do not match, you need to specify how to match the names (in your example, add "p_" and make it lowercase). One possibility is to fix the mapping .

If you defined the whole community, it would be something like this:

 public TResult GetById<TResult, TEntity>(int id) { using (DBEntities dbe = new DBEntities()) { T result = dbe.StoreTables.Set<T>.Find(new object[] {key}); var mapper = ObjectMapperManager.DefaultInstance .GetMapper<TEntity, TResult>( new DefaultMapConfig().MatchMembers((m1, m2) => "p_" + m1.ToLower() == m2)); return mapper.Map(result); } } 
+2
source

All Articles