2011-01-24 13 views
17

आईव का उपयोग करके एप्लिकेशन ने उपरोक्त तकनीकों के साथ कुछ बेस प्रोजेक्ट बनाने की कोशिश की। मैं अधिकतम लचीलापन और टेस्टेबिलिटी चाहता था इसलिए मैंने इसे भविष्य की परियोजनाओं के आधार के रूप में बनाने के तरीके के साथ पैटर्न का उपयोग करने की कोशिश की। हालांकि, ऐसा लगता है कि कुछ गलत है या जो कुछ भी है और मुझे वास्तव में यहां सहायता चाहिए। तो मेरे पास दो प्रश्न हैं:एएसपी.नेट एमवीसी 3 निनजेक्ट, एंटिटी फ्रेमवर्क 4 कोड-फर्स्ट सीटीपी 5, पैटर्न

1- क्या मेरे वर्तमान कोड में कुछ गड़बड़ है? Ive सही ढंग से लागू पैटर्न? कोई सुझाव या सिफारिश जो मुझे सही दिशा में ले जायेगी?

2- यह कोड वास्तव में डेटाबेस से कनेक्ट क्यों होता है, इसे बनाते हैं, लेकिन अगर मैं सुधार ऑपरेशन करता हूं तो भी सम्मिलित करने का समर्थन नहीं करता है? (इस त्रुटि के बारे में विवरण के लिए पोस्ट के अंत को देखें) ** फिक्स्ड **

मुझे विश्वास है कि यह दूसरों की भी मदद कर सकता है क्योंकि मुझे कुछ सही तरीके से करने के लिए पर्याप्त जानकारी मिली है। मुझे पूरा यकीन है कि बहुत सारे लोग इसे सही तरीके से करने की कोशिश करते हैं और मेरे जैसे निश्चित नहीं हैं कि मैं जो कर रहा हूं वह सही है।

मैं दो संस्थाओं है: टिप्पणी और समीक्षा

टिप्पणी

public class Comment 
{ 
[Key] 
public virtual int Id { get; set; } 

public virtual string Name { get; set; } 
public virtual string Author { get; set; } 
public virtual string Body { get; set; } 
} 

समीक्षा

public class Review 
{ 
[Key] 
public virtual int Id { get; set; } 

public virtual string Name { get; set; } 
public virtual string Author { get; set; } 
public virtual string Body { get; set; } 
public virtual bool Visible { get; set; } 

public IEnumerable<Comment> Comments { get; set; } 
} 

मैं उनमें से प्रत्येक के इस तरह के लिए एक आधार भंडार का निर्माण:

public class EFReviewRepository : EFRepositoryBase<Review>, IReviewRepository 
{ 
public EFReviewRepository(IDatabaseFactory databaseFactory) 
    : base(databaseFactory) 
{ } 

public IEnumerable<Review> FindByAuthor(string author) 
{ 
    return base.Database.Reviews.Where(r => r.Author.StartsWith(author)) 
    .AsEnumerable<Review>(); 
} 
} 
:

public interface IReviewRepository : IRepository<Review> { 
// Add specific review operations 
IEnumerable<Review> FindByAuthor(string author); 
} 

तो मैं सार वर्ग से जेनरिक संचालन के साथ साथ विशिष्ट कार्यों हो रही है:

जेनेरिक भंडार

public abstract class EFRepositoryBase<T> : IRepository<T> where T : class 
{ 
private Database _database; 
private readonly IDbSet<T> _dbset; 

protected IDatabaseFactory DatabaseFactory { get; private set; } 
protected Database Database { get { return _database ?? (_database = DatabaseFactory.Get()); } } 

public EFRepositoryBase(IDatabaseFactory databaseFactory) 
{ 
    DatabaseFactory = databaseFactory; 
    _dbset = Database.Set<T>(); 
} 

public virtual void Add(T entity) 
{ 
    _dbset.Add(entity); 
} 

public virtual void Delete(T entity) 
{ 
    _dbset.Remove(entity); 
} 

public virtual T GetById(long id) 
{ 
    return _dbset.Find(id); 
} 

public virtual IEnumerable<T> All() 
{ 
    return _dbset.ToList(); 
} 
} 

विशिष्ट कार्यों के लिए, मैं एक इंटरफ़ेस का उपयोग

जैसा कि आपने सोचा था, मैं डेटाबेस डेटाबेस का भी उपयोग करता हूं ry डेटाबेस संदर्भ का उत्पादन करेगा:

डेटाबेस फैक्टरी

public class DatabaseFactory : Disposable, IDatabaseFactory 
{ 
private Database _database; 

public Database Get() 
{ 
    return _database ?? (_database = new Database(@"AppDb")); 
} 

protected override void DisposeCore() 
{ 
    if (_database != null) 
    _database.Dispose(); 
} 
} 

डिस्पोजेबल (कुछ एक्सटेंशन तरीकों ...)

public class Disposable : IDisposable 
{ 
private bool isDisposed; 

~Disposable() 
{ 
    Dispose(false); 
} 

public void Dispose() 
{ 
    Dispose(true); 
    GC.SuppressFinalize(this); 
} 
private void Dispose(bool disposing) 
{ 
    if (!isDisposed && disposing) 
    { 
    DisposeCore(); 
    } 

    isDisposed = true; 
} 

protected virtual void DisposeCore() 
{ 
} 
} 

डेटाबेस

public class Database : DbContext 
{ 
private IDbSet<Review> _reviews; 

public IDbSet<Review> Reviews 
{ 
    get { return _reviews ?? (_reviews = DbSet<Review>()); } 
} 

public virtual IDbSet<T> DbSet<T>() where T : class 
{ 
    return Set<T>(); 
} 

public Database(string connectionString) 
    : base(connectionString) 
{ 
    //_reviews = Reviews; 
} 

public virtual void Commit() 
{ 
    base.SaveChanges(); 
} 

/* 
protected override void OnModelCreating(ModelBuilder modelBuilder) 
{ 
    // TODO: Use Fluent API Here 
} 
*/ 
} 

और समाप्त करने के लिए, मेरे पास काम की मेरी इकाई है ....,

Ninject नियंत्रक फैक्टरी

public class NinjectControllerFactory : DefaultControllerFactory 
{ 
// A Ninject "Kernel" is the thing that can supply object instances 
private IKernel kernel = new StandardKernel(new ReviewsDemoServices()); 

// ASP.NET MVC calls this to get the controller for each request 
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) 
{ 
    if (controllerType == null) 
    return null; 
    return (IController)kernel.Get(controllerType); 
} 

private class ReviewsDemoServices : NinjectModule 
{ 
    public override void Load() 
    { 
    // Bindings... 
    Bind<IReviewRepository>().To<EFReviewRepository>(); 
    Bind<IUnitOfWork>().To<UnitOfWork>(); 
    Bind<IDatabaseFactory>().To<DatabaseFactory>(); 
    Bind<IDisposable>().To<Disposable>(); 
    } 
} 
} 
हालांकि

जब मैं निर्माता में फोन (:

काम

public class UnitOfWork : IUnitOfWork 
{ 
private readonly IDatabaseFactory _databaseFactory; 
private Database _database; 

public UnitOfWork(IDatabaseFactory databaseFactory) 
{ 
    _databaseFactory = databaseFactory; 
} 

protected Database Database 
{ 
    get { return _database ?? (_database = _databaseFactory.Get()); } 
} 

public void Commit() 
{ 
    Database.Commit(); 
} 
} 

की यूनिट मैं भी Ninject इंटरफेस का उपयोग कर आबद्ध डिफ़ॉल्ट कार्रवाई) ...

public class ReviewController : Controller 
    { 
     private readonly IReviewRepository _reviewRepository; 
     private readonly IUnitOfWork _unitOfWork; 

     public ReviewController(IReviewRepository postRepository, IUnitOfWork unitOfWork) 
     { 
      _reviewRepository = postRepository; 
      _unitOfWork = unitOfWork; 
     } 

     public ActionResult Index() 
     { 
      Review r = new Review { Id = 1, Name = "Test", Visible = true, Author = "a", Body = "b" }; 
      _reviewRepository.Add(r); 
      _unitOfWork.Commit(); 

      return View(_reviewRepository.All()); 
     } 

    } 

ऐसा लगता है कि डेटाबेस बना रहा है लेकिन EF4 में डेटाबेस में कुछ भी सम्मिलित नहीं करता है।

ServerVersion = '(((System.Data.Entity.DbContext (_database)).Database.Connection).ServerVersion' threw an exception of type 'System.InvalidOperationException' 

मैं सही चीजें कर रहा हूँ: यह प्रतीत कि मैं समस्या समझ सकता है .. जबकि डेटाबेस वस्तु को देख .. कनेक्शन राज्य बंद कर दिया है और सर्वर संस्करण इस तरह का एक अपवाद फेंक? क्या आईव निर्मित में कुछ गड़बड़ है?

यदि आपके द्वारा पोस्ट किए गए कोड के बारे में सिफारिश की गई है, तो भी मुझे खुशी होगी। मैं सिर्फ एमवीसी 3 में किसी भी तरह के आवेदन के निर्माण के लिए सही तरीके से सीखने की कोशिश कर रहा हूं। मुझे अच्छी शुरूआत चाहिए।

मैं का उपयोग करें:

  • इकाई की रूपरेखा 4 कोड-प्रथम

  • ASP.NET MVC 3

  • Ninject डि के रूप में कंटेनर

  • SQL सर्वर एक्सप्रेस के साथ (नहीं आर 2)

  • विजुअल स्टूडियो 2010 वेब एक्सप्रेस

आपकी मदद के लिए बहुत बहुत धन्यवाद!

+0

को संशोधित करने से अपने कार्य की कॉल को रोकने के लिए चाहते हैं कभी कभी का उपयोग कर IEnumerable<> मान्य है -

फिर, यह जानबूझकर किया जा सकता है ? मुझे इस तरह कुछ देखने में दिलचस्पी है। मैंने Kazi Manzur Rashid @ http://shrinkr.codeplex.com/ –

+0

द्वारा लिखे गए संकीर्ण एप्लिकेशन में समान पैटर्न देखा है, मुझे लगता है कि यह कोड मूल रूप से http://myfinance.codeplex.com/ – woggles

+1

से एकत्रित हुआ था इस कोड के आस-पास अन्य लोगों के इस पोस्ट के साथ-साथ कोई भी व्यक्ति जिसने बात की वह क्षेत्र में वास्तव में विशेषज्ञ है। दूसरों के चारों ओर घूमने में मदद करने के लिए यहां मेरा पूरा कोड डालने का मेरा इरादा था। – Rushino

उत्तर

11

ई। यह एक चुस्त था। असल में मुझे बहुत ज्यादा पता नहीं है इसलिए मैं इसे तुरंत समझ नहीं पाया।

मुझे दूसरे प्रश्न के लिए समाधान मिला जो त्रुटि से संबंधित था, यह पता लगाकर कि निंजा वास्तव में डेटाबेस फैक्टरी के दो उदाहरण शूट करता है, एक भंडार के लिए और एक काम की इकाई के लिए। असल में, त्रुटि समस्या नहीं थी। यह ऑब्जेक्ट डेटाबेस में एक आंतरिक त्रुटि थी, लेकिन यह सामान्य है कि मैं एंटिटी फ्रेमवर्क का उपयोग कर रहा हूं।

वास्तविक समस्या यह थी कि निनजेक्ट IDatabaseFactory के दो अलग-अलग उदाहरण को बाध्यकारी कर रहा था जिससे 2 कनेक्शन खुल जाते हैं।

समीक्षा _reviewRepostory में पहले सेट में जोड़ा गया था जो डेटाबेस के पहले उदाहरण का उपयोग कर रहा था।

काम की इकाई पर प्रतिबद्धता कॉल करते समय .. इस तथ्य के कारण यह कुछ भी नहीं बचा कि समीक्षा इस डेटाबेस उदाहरण पर नहीं थी। वास्तव में, काम की इकाई डेटाबेसफैक्टरी कहलाती है जो एक नया उदाहरण बनाने के लिए प्रेरित करती है क्योंकि निंजेक्ट ने इसका एक नया उदाहरण भेजा है।

इसे ठीक करने के लिए बस का उपयोग करें:

Bind<IDatabaseFactory>().To<DatabaseFactory>().InSingletonScope(); 

बजाय

Bind<IDatabaseFactory>().To<DatabaseFactory>(); 

और अब सभी सिस्टम काम सही ढंग से!

अब, पहले प्रश्न के बारे में कुछ जवाब पसंद आएगा जो मेरे वर्तमान कोड के साथ कुछ गलत था? Ive सही ढंग से लागू पैटर्न? कोई सुझाव या सिफारिश जो मुझे सही दिशा में ले जायेगी?

+9

हो सकता है कि आप InSingletonScope को InRequestScope (https://github.com/ninject/ninject/wiki/Object-Scopes) में बदलना चाहें। वेब-अनुरोधों के बीच राज्य को बनाए रखना बेहतर नहीं है। जैसे InSingletonScope के साथ मुझे लगता है कि दो उपयोगकर्ता दोनों एक ही उदाहरण प्राप्त कर सकते हैं, हो सकता है कि आप इसे नहीं चाहें। डिफ़ॉल्ट InTransientScope है: "प्रत्येक बार अनुरोध किए जाने पर प्रकार का एक नया उदाहरण बनाया जाएगा।", जो आपकी त्रुटि उत्पन्न कर रहा था। –

+0

क्या आप समझा सकते हैं कि आप अपनी संस्थाओं का निपटान कैसे कर रहे हैं, क्योंकि मुझे नियंत्रक के अंदर कोई भी विधि दिखाई नहीं देती है जो निपटान करती है। मैंने देखा कि निपटान नाम का वर्ग है, लेकिन मैं यह समझने में असमर्थ हूं कि वह वर्ग तस्वीर में कैसे आता है और निपटान करता है। –

+0

निपटान विधि केवल कारखाने के लिए है, – Rushino

5

एक छोटा सा अवलोकन: अपने EFRepositoryBase और IReviewRepository होने से तरीकों कि वापसी एक IEnumerable<> के बजाय एक IQueryable<>, आप क्वेरी के लिए फिल्टर भाव/कमी या अनुमानों या इतने पर जोड़ने से बाद के तरीकों को रोकने के लिए है। इसके बजाय, IEnumerable<> का उपयोग करके, आप डेटा ऑपरेटर के विरुद्ध चलने वाले SQL कथन को प्रभावित करने और सरल बनाने के बजाय, उन परिणामों को पूर्ण परिणाम सेट पर किसी भी बाद के फ़िल्टरिंग (जैसे LINQ एक्सटेंशन विधियों का उपयोग करके) करेंगे।

दूसरे शब्दों में, आप वेबसर्वर स्तर पर आगे फ़िल्टरिंग कर रहे हैं, डेटाबेस स्तर पर नहीं, जहां यह वास्तव में संभव है। अगर आप कहाँ इकाई के साथ इस के लिए गपशप मिला एसक्यूएल कि उत्पन्न होता है, आदि

+2

इस टिप्पणी ने मेरे प्रोजेक्ट के आर्किटेक्चर के बारे में कुछ प्रश्नों को मंजूरी दे दी। मुझे लगता है कि मुझे 'IQueryable <>' '' IENumerable <> 'से अधिक उपयोग करने की आवश्यकता है, लेकिन तर्क पर 100% स्पष्ट नहीं था। धन्यवाद। – Ecnalyr

संबंधित मुद्दे