Issue in Connecting Web App with localdb using DataContext file and webConfig file - asp.net-mvc

I have created MVC web application using Repository & DI approach. I have used Code First approach too.
Here is my DataContext file:
namespace EfRepPatTest.Data
{
public class DataContext : DbContext, IDbContext
{
public new IDbSet<TEntity> Set<TEntity>() where TEntity: class
{
return base.Set<TEntity>();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var typesToRegister = Assembly.GetExecutingAssembly().GetTypes()
.Where(type => !String.IsNullOrEmpty(type.Namespace))
.Where(type => type.BaseType != null && type.BaseType.IsGenericType &&
type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));
foreach (var type in typesToRegister)
{
dynamic configurationInstance = Activator.CreateInstance(type);
modelBuilder.Configurations.Add(configurationInstance);
}
base.OnModelCreating(modelBuilder);
}
}
}
I have defined connecting string in Web.Config file like below:
<add name="DataContext"
connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\eCommerce.mdf;Integrated Security=True"
providerName="System.Data.SqlClient"
/>
Please note here I have mentioned same name to the Connection string and my context file.
Here is my post method:
[HttpPost]
public ActionResult Create(CategoryModel model)//FormCollection collection
{
try
{
// TODO: Add insert logic here
if (model == null)
return View(model);
var category = new Category();
category.Name = model.Name;
categoryService.Insert(category);
return RedirectToAction("Index");
}
catch
{
return View(model);
}
}
CategoryService:
public class CategoryService : ICategoryService
{
private IRepository<Category> _categoryRepository;
public CategoryService(IRepository<Category> categoryRepository)
{
this._categoryRepository = categoryRepository;
}
public void Insert(Category category)
{
if (category == null)
throw new ArgumentNullException("Category");
_categoryRepository.Insert(category);
}
}
RepositoryService:
public class RepositoryService<TEntity> : IRepository<TEntity> where TEntity: class
{
private IDbContext _context;
private IDbSet<TEntity> Entities
{
get { return this._context.Set<TEntity>(); }
}
public RepositoryService(IDbContext context)
{
this._context = context;
}
public void Insert(TEntity entity)
{
Entities.Add(entity);
}
}
When I run application on the first time it will create local db. But when I going to insert data, I did not get any error from the application and it does not insert my data to the DB.
What cause this? What I have done wrong here?
Any help is appreciated!

You should call SaveChanges() on _context after all changes like this for ex.:
public void Insert(TEntity entity)
{
Entities.Add(entity);
_context.SaveChanges();
}

Related

When querying SQL with EF6 from a WebJob, query fails because it's trying to get a pluralized version of the table

My code looks like this:
public static void DoSomething(TextWriter log)
{
log.WriteLine("Hey man! I'm running!");
try
{
using (MyDBContext context = new MyDBContext())
{
MemberMaster mm = context.MemberMaster.SingleOrDefault(m => m.MemberMasterId == 1);
if (mm != null)
{
log.WriteLine(string.Format("MemberMasterId = {0}, Username = {1}", mm.MemberMasterId, mm.UserName));
}
else
{
log.WriteLine("Could not find Member with MembermasterId = 1");
}
}
}
catch (Exception ex)
{
log.WriteLine(ex.Message);
}
log.WriteLine("Done!");
}
MyDBContext.cs looks like this:
public class MyDBContext : DbContext
{
public MyDBContext() : this("MyDb")
{
}
public MyDBContext(string connectionName) : base(connectionName) { }
public DbSet<MemberMaster> MemberMaster { get; set; }
}
I've tried to add a modelBuilder to remove Pluralizing names but that simply results in an error about the DB Context having changed....use code first...etc..etc...
Is there a better way to do this? The WebJob is being deployed via AZure with a .ZIP file and resides in the same AppService as my Website.
I turn off plurallizing on Sets and Tables by overriding the OnModelCreating, to keep both named the same, and have had no problem:
public class MyDBContext : DbContext
{
static MyDBContext()
{
Database.SetInitializer<DbContext>(null);
}
public MyDBContext() : this("MyDb")
{
}
public MyDBContext(string connectionName) : base(connectionName) { }
public DbSet<MemberMaster> MemberMaster { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingEntitySetNameConvention>();
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
}
}

Error while creating plugin in Nop Commerce

This is my first demo project in Nopcommerce and i have tried to make my own plugin but during the time of Build some error is seen. Below are some codes.
namespace Nop.Plugin.Aowi.Testimonial.Data
{
public class TestimonialRecordObjectContext : DbContext , IDbContext
{
public TestimonialRecordObjectContext(string nameOrConnectionString) : base(nameOrConnectionString) { }
#region Implementation of IDbContext
#endregion
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new TestimonialRecordMap());
base.OnModelCreating(modelBuilder);
}
public string CreateDatabaseInstallationScript()
{
return ((IObjectContextAdapter)this).ObjectContext.CreateDatabaseScript();
}
public void Install()
{
//It's required to set initializer to null (for SQL Server Compact).
//otherwise, you'll get something like "The model backing the 'your context name' context has changed since the database was created. Consider using Code First Migrations to update the database"
Database.SetInitializer<TestimonialRecordObjectContext>(null);
Database.ExecuteSqlCommand(CreateDatabaseInstallationScript());
SaveChanges();
}
public void Uninstall()
{
var dbScript = "DROP TABLE Testimonial";
Database.ExecuteSqlCommand(dbScript);
SaveChanges();
}
public new IDbSet<TEntity> Set<TEntity>() where TEntity : BaseEntity
{
return base.Set<TEntity>();
}
public System.Collections.Generic.IList<TEntity> ExecuteStoredProcedureList<TEntity>(string commandText, params object[] parameters) where TEntity : BaseEntity, new()
{
throw new System.NotImplementedException();
}
public System.Collections.Generic.IEnumerable<TElement> SqlQuery<TElement>(string sql, params object[] parameters)
{
throw new System.NotImplementedException();
}
public int ExecuteSqlCommand(string sql, bool doNotEnsureTransaction = false, int? timeout = null, params object[] parameters)
{
throw new System.NotImplementedException();
}
}
}
This is the Dependency registrar part
namespace Nop.Plugin.Aowi.Testimonial.Infastructure
{
public class DependencyRegistrar: IDependencyRegistrar
{
private const string CONTEXT_NAME ="nop_object_context_product_view_tracker";
public virtual void Register(ContainerBuilder builder, ITypeFinder typeFinder, NopConfig config)
{
//data context
this.RegisterPluginDataContext<TestimonialRecordObjectContext>(builder, CONTEXT_NAME);
//override required repository with our custom context
builder.RegisterType<EfRepository<TestimonialRecord>>()
.As<IRepository<TestimonialRecord>>()
.WithParameter(ResolvedParameter.ForNamed<IDbContext>(CONTEXT_NAME))
.InstancePerLifetimeScope();
}
public int Order
{
get { return 1; }
}
}
}
Even after cleaning and Building i am getting this error.
Can anyone help me with this. I have done all of this by watching a tutorial so if anyone can help me correct my mistake i will be really greatful.
You just need to implement this method and properties of IDbContext interface, which are described in error log, in your custom context.
for example, how it is done in one of the existing plugin Tax.CountryStateZip:
public void Detach(object entity)
{
if (entity == null)
throw new ArgumentNullException("entity");
((IObjectContextAdapter)this).ObjectContext.Detach(entity);
}
public virtual bool ProxyCreationEnabled
{
get { return this.Configuration.ProxyCreationEnabled; }
set { this.Configuration.ProxyCreationEnabled = value; }
}
public virtual bool AutoDetectChangesEnabled
{
get { return this.Configuration.AutoDetectChangesEnabled; }
set { this.Configuration.AutoDetectChangesEnabled = value; }
}
I cannot get an idea from your code that where is actual issue. But i suggest by an example.
make your install method code like:
public void Install()
{
//create the table
var dbScript = CreateDatabaseScript();
Database.ExecuteSqlCommand(dbScript);
SaveChanges();
}
Add a new class called EfStartUpTask and paste following code:
public class EfStartUpTask : IStartupTask
{
public void Execute()
{
//It's required to set initializer to null (for SQL Server Compact).
//otherwise, you'll get something like "The model backing the 'your context name' context has changed since the database was created. Consider using Code First Migrations to update the database"
Database.SetInitializer<YourContext>(null);
}
public int Order
{
//ensure that this task is run first
get { return 0; }
}
}
And your DependencyRegistrar :
public class DependencyRegistrar : IDependencyRegistrar
{
public virtual void Register(ContainerBuilder builder, ITypeFinder typeFinder)
{
builder.RegisterType<YourService>().As<YourserviceInterface>().InstancePerLifetimeScope();
//data context
this.RegisterPluginDataContext<YourContext>(builder, "nop_object_context_product_view_tracker");
//override required repository with our custom context
builder.RegisterType<EfRepository<YourEntityClass>>()
.As<IRepository<YourEntityClass>>()
.WithParameter(ResolvedParameter.ForNamed<IDbContext>("nop_object_context_product_view_tracker"))
.InstancePerLifetimeScope();
}
public int Order
{
get { return 1; }
}
}
Note: you have to change YourContext to your context name and same as for entity class
Hope this helps!

How do I use multiple databases with Autofac?

I am having a project and my project is connecting to two different databases are BookStoreEntities and BlogEntities.
If I remove line code builder.RegisterType<BlogEntities>().As<DbContext>(); in Autofac configuration my project works fine and else I'll get error "The entity type Book is not part of the model for the current context".
My autofac config:
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterType<BookStoreEntities>().As<DbContext>();
builder.RegisterType<BlogEntities>().As<DbContext>();
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)).InstancePerDependency();
builder.RegisterType<BookService>().As<IBookService>();
builder.RegisterFilterProvider();
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
Repository class:
public class Repository<T> : IRepository<T> where T : class
{
private DbContext _dbContext;
private DbSet<T> _dbSet;
public Repository(DbContext dbContext)
{
_dbContext = dbContext;
_dbSet = dbContext.Set<T>();
}
public IEnumerable<T> GetAll()
{
return _dbSet;
}
}
Service layer:
public class BookService : IBookService
{
private IRepository<Book> _bookRepository;
public BookService(IRepository<Book> bookRepository)
{
_bookRepository = bookRepository;
}
public IEnumerable<Book> GetBooks()
{
return _bookRepository.GetAll();
}
}
Controller:
public class BookController : Controller
{
private IBookService _bookService;
public BookController(IBookService bookService)
{
_bookService = bookService;
}
// GET: Book
public ActionResult Index()
{
var books = _bookService.GetBooks();
return View(books);
}
}
My Project is using 2 different databases and Service layer will implement from this Generic Repository. I want to myservice1 works with MyDbContext1 and myservice2 works with MyDbContext2
Then don't new your DbContext inside your repository. That makes testing hard anyway.
Inject it:
public Repository(DbContext dbContext)
{
_dbContext = dbContext;
}
Now the repository doesn't care which DbContext-derived class is injected. This works because you only call DbContext.Set<T>().
Try to something like:
public class MyDbContext1 : DbContext
{
public MyDbContext1 ()
:base("ConnectionString")
{ }
public new IDbSet<TEntity> Set<TEntity>() where TEntity : class
{
return base.Set<TEntity>();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//...
}
}
And add to repository new property
private IDbSet<T> Entities
{
get
{
if (_dbSet == null)
{
_dbSet = _dbContext1.Set<T>();
}
return _dbSet;
}
}

Entity Framework, Unity, and MVC

I have a multi tier application using Entity Framework, MVC and Unity.
The basic setup is like this:
EF Data Access Layer
public class MyDataProvider : DbContext, IMyDataProvider
{
public MyDataProvider(SqlConnection existingConnection, bool contextOwnsConnection)
: base(existingConnection,contextOwnsConnection)
{
((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 60;
Configuration.LazyLoadingEnabled = true;
Configuration.ValidateOnSaveEnabled = true;
Configuration.ProxyCreationEnabled = true;
Configuration.AutoDetectChangesEnabled = true;
}
public new IDbSet<TModel> Set<TModel>() where TModel : class
{
return base.Set<TModel>();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new EmployeeMapping());
base.OnModelCreating(modelBuilder);
}
public abstract class ServiceBase<TModel> : IDisposable, IService<TModel> where TModel : class, IModel
{
[Dependency]
public IMyDataProvider MyDataProvider { get; set; }
...
}
All services inherit from this class
I then inject specific services into the Business Logic Layer like so:
public class GetEmployees
{
[Dependency("EmployeeService")]
public IEmployeeService EmployeeService { get; set;
public IQueryable<Employee> GetAllEmployees()
{
return EmployeeService.GetTable();
}
...
}
In MVC I use a controller factory
public class MyControllerFactory : DefaultControllerFactory
{
private IUnityContainer _container;
public MyControllerFactory(IUnityContainer container)
{
_container = container;
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType != null)
{
return _container.Resolve(controllerType) as IController;
}
else
{
return base.GetControllerInstance(requestContext, controllerType);
}
}
Global.asax
private static IUnityContainer InitContainer()
{
IUnityContainer unityContainer = new UnityContainer();
Bootstrapper bootstrapper = new Bootstrapper(unityContainer);
return unityContainer;
}
I pass the instance of UnityContainer into the Bootstrapper class. The Bootstrapper class self registers all assemblies.
In the MVC Controllers, I inject the Business Logic like so:
public class EmployeeController
{
[Dependency("GetEmployees")]
public IBusinessLogic GetEmployees_Operations { get; set; }
public ActionResult EmployeeMain()
{
var employees = GetEmployees_Operations.GetAllEmployees();
...
}
}
This all works great up to a point. Every so often I will get an exception thrown from MyDataProvider class: "EntityConnection can only be constructed with a closed DbConnection". This seems to happen during high use of the MVC site. The exception is simple enough to understand, but how should I go about fixing it?
I found that changing how I instantiate the business logic class from a field on the controller to inside the ActionResult method, I don't recieve the exception.
For example:
public class EmployeeController
{
//[Dependency("GetEmployees")]
//public IBusinessLogic GetEmployees_Operations { get; set; }
public ActionResult EmployeeMain()
{
IBusinessLogic GetEmployees_Operations = _ioc_Bootstrapper.Resolve(typeof(IBusinessLogic), "GetEmployees") as IBusinessLogic;
var employees = GetEmployees_Operations.GetAllEmployees();
...
}
}
Have I completely missed the boat on this and implemented Unity incorrectly?
Bootstrapper code
private void RegisterDAL(String assembly)
{
var currentAssembly = Assembly.LoadFrom(assembly);
var assemblyTypes = currentAssembly.GetTypes();
foreach (var assemblyType in assemblyTypes)
{
...
if (assemblyType.FullName.EndsWith("Provider"))
{
foreach (var requiredInterface in assemblyType.GetInterfaces())
{
if (requiredInterface.FullName.EndsWith("DataProvider"))
{
var typeFrom = assemblyType.GetInterface(requiredInterface.Name);
var typeTo = assemblyType;
var injector = GetInjectorConstructor(assemblyType.Module.Name);
RegisterType(typeFrom, typeTo, false, injector);
}
}
continue;
}
...
}
private InjectionConstructor GetInjectorConstructor(String moduleName)
{
...
connString = String.Concat("Data Source=MySqlServer, ";Initial Catalog=", catalogName, ";Application Name=", applicationName, ";Integrated Security=True; );
var conn = new SqlConnection(connString);
return new InjectionConstructor(conn, true);
}

The object cannot be deleted because it was not found in the ObjectStateManager

I have something like this:
public void Delete(T entity)
{
Context.DeleteObject(entity);
Context.SaveChanges();
}
I end up wit a exception:
"The object cannot be deleted because it was not found in the ObjectStateManager."
If I try to add the entity to objectContext with AttachTo() I get:
"An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key."
Whats wrong?
Example:
namespace CAFM.Data.Repository
{
public abstract class RepositoryBase<T> : IRepository<T>
where T : EntityObject
{
public RepositoryBase()
: this(new CAFMRepositoryContext())
{
}
static RepositoryBase()
{
}
public RepositoryBase(IRepositoryContext repositoryContext)
{
_context = repositoryContext ?? new CAFMRepositoryContext();
_entity = _repositoryContext.ObjectContext.CreateObjectSet<T>();
}
private readonly ObjectContext _context;
private readonly ObjectSet<T> _entity;
protected ObjectContext Context
{
get { return _context; }
}
protected IObjectSet<T> Entity
{
get { return _entity; }
}
#region IRepository Members
private string GetEntityName()
{
return string.Format("{0}.{1}", _entity.EntitySet.EntityContainer, _entity.EntitySet.Name);
}
public T Add(T entity)
{
var fqen = GetEntityName();
Context.AddObject(fqen, entity);
Context.SaveChanges(SaveOptions.AcceptAllChangesAfterSave);
return entity;
}
public T Update(T entity)
{
Context.ApplyCurrentValues(GetEntityName(), entity);
Context.SaveChanges(SaveOptions.AcceptAllChangesAfterSave);
return entity;
}
public void Delete(T entity)
{
Context.DeleteObject(entity);
Context.SaveChanges();
}
#endregion
}
}
You have to fetch the entity you wish to delete from your context first. Best to do this with a comparison of the primary key. It could look like this, but i do not know the object structure of TabMaster and TabMasterViewModel, so the properties may be wrong named.
public void Delete(TabMasterViewModel entity) {
TabMaster des = _tabmasterRepository.FirstOrDefault( e.Id = entity.ID );
if (des != null) {
_tabmasterRepository.Delete(des);
}
}
You have created a new Entity and mapped the values from your view model to that entity. But the context does not know of the entity, so he could not delete it.
You could just "Attach" the object to the current context like that:
public void Delete(T entity)
{
context.AttachTo(entity.EntityKey.EntitySetName, entity);
Context.DeleteObject(entity);
Context.SaveChanges();
}

Resources