Merging these two very similar methods
<p>I have these two methods on a service:</p>

<pre><code>public Offer GetOffer(int id, string languageCode = Website.LanguageSettings.DefaultLanguageCode)
        {
            Entities.Offer offerEntity = _db.Offers.FirstOrDefault(offer =&gt; offer.Id == id);

            if (languageCode.ToLower(CultureInfo.InvariantCulture) != Website.LanguageSettings.DefaultLanguageCode)
            {
                using (IDocumentSession session = store.OpenSession())
                {
                    Translation.Offer translatedOffer = session.LuceneQuery&lt;Translation.Offer&gt;(Website.RavenDbSettings.Indexes.Offers)
                        .Where(string.Format("ObjectId:{0} AND LanguageCode:{1}", id, languageCode))
                        .OrderByDescending(offer =&gt; offer.Id)
                        .FirstOrDefault();

                    var offerPOCO = Mapper.DynamicMap&lt;Translation.Offer, Offer&gt;(translatedOffer);
                    offerPOCO.Id = offerEntity.Id;

                    return offerPOCO;
                }
            }

            return Mapper.Map&lt;Entities.Offer, Offer&gt;(offerEntity);
        }
</code></pre>

<p>And</p>

<pre><code>public Hotel GetHotel(int id, string languageCode = Website.LanguageSettings.DefaultLanguageCode)
        {
            Entities.Hotel hotelEntity = _db.Hotels.FirstOrDefault(hotel =&gt; hotel.Id == id);

            if (languageCode.ToLower(CultureInfo.InvariantCulture) != Website.LanguageSettings.DefaultLanguageCode)
            {
                using(IDocumentSession session = store.OpenSession())
                {
                    Translation.Hotel translatedHotel = session.LuceneQuery&lt;Translation.Hotel&gt;(Website.RavenDbSettings.Indexes.Hotels)
                        .Where(string.Format("ObjectId:{0} AND LanguageCode:{1}", id, languageCode))
                        .OrderByDescending(hotel =&gt; hotel.Id)
                        .FirstOrDefault();

                    Hotel hotelPOCO = Mapper.DynamicMap&lt;Translation.Hotel, Hotel&gt;(translatedHotel);
                    hotelPOCO.Id = hotelEntity.Id;

                    return hotelPOCO;
                }
            }

            return Mapper.Map&lt;Entities.Hotel, Hotel&gt;(hotelEntity);
        }
</code></pre>

<p>They are exactly the same in most aspects: they take the same params, build the same query and make the same operations, the only thing that varies is the type of objects they work with and output. Besides building a method to generate the Where() param string, I can't think of any way I can merge most (or all) of this code into a single method and then just call it from the GetOffer() and GetHotel() methods since I'll end up with several more just like these two.</p>

<p>Any advice is greatly appreciated.</p>

<p>Edit: adding the solution so if another poor soul comes across this problem he/she can have a starting point:</p>

<pre><code>private TReturn GetObject&lt;TReturn, TEntity, TTranslation&gt;(int id, string languageCode, string ravenDbIndex) where TEntity:EntityObject 
                                                                                                                    where TTranslation:Translation.BaseTranslationObject
                                                                                                                    where TReturn:BasePOCO
        {
            // TODO Run more tests through the profiler
            var entities = _db.CreateObjectSet&lt;TEntity&gt;();
            var entityKey = new EntityKey(_db.DefaultContainerName + "." + entities.EntitySet.Name, "Id", id); // Sticking to the Id convention for the primary key
            TEntity entity = (TEntity)_db.GetObjectByKey(entityKey);

            if(languageCode.ToLower(CultureInfo.InvariantCulture) != Website.LanguageSettings.DefaultLanguageCode)
            {
                using(IDocumentSession session = store.OpenSession())
                {
                    TTranslation translatedObject = session.LuceneQuery&lt;TTranslation&gt;(ravenDbIndex)
                        .Where(string.Format("ObjectId:{0} AND LanguageCode:{1}", id, languageCode))
                        .OrderByDescending(translation =&gt; translation.Id)
                        .FirstOrDefault();

                    TReturn poco = Mapper.DynamicMap&lt;TTranslation, TReturn&gt;(translatedObject);
                    poco.Id = id;

                    return poco;
                }
            }

            return Mapper.Map&lt;TEntity, TReturn&gt;(entity);
        }
</code></pre>

<p>And then I just call:</p>

<pre><code>GetObject&lt;Hotel, Entities.Hotel, Translation.Hotel&gt;(id, languageCode, Website.RavenDbSettings.Indexes.Hotels);
</code></pre>

<p>Whenever I need a hotel.</p>

<p>Thank you all for the great replies, learned quite a lot from them.</p>
