How to customize the pluralization EF6 - c#

I'm trying to use the interface IPluralizationService to customize the pluralization of my entities without success!
Necessary that all entities are pluralized using the Inflector library.
Attempts
class Config : DbConfiguration
{
public Config()
{
SetPluralizationService(new CustomPluralization());
}
}
class CustomPluralization : IPluralizationService
{
public string Pluralize(string word)
{
return word.Pluralize();
}
public string Singularize(string word)
{
return word.Singularize();
}
}
In my context;
modelBuilder.Configurations.Add<Config>(.. ?? ..)

According to msdn's article Code-Based Configuration (EF6 onwards) section Using DbConfiguration, it is sufficient to simply place your DbConfiguration class in the same assembly as your DbContext class.
Nevertheless you can specify it manually, as explained in the article by using either the config file or an annotation in your DbContext.
Config file:
<entityFramework codeConfigurationType="MyNamespace.MyDbConfiguration, MyAssembly">
<!-- Your EF config -->
</entityFramework>
Annotation:
[DbConfigurationType("MyNamespace.MyDbConfiguration, MyAssembly")]
public class MyContextContext : DbContext
{
}
Or
[DbConfigurationType(typeof(MyDbConfiguration))]
public class MyContextContext : DbContext
{
}
Note:
These examples are directly from the article I linked

Related

Using the DbConfiguration class with Entity Framework ObjectContext

I have a C# application using Entity Framework and ObjectContext. I wish to implement connection resiliency like mentioned here: https://msdn.microsoft.com/en-us/library/dn456835(v=vs.113).aspx
How do I assign the DbConfiguration class to the ObjectContext (i.e. how do I 'tell' the ObjectContext to use the configuration)?
You can provide a configuration class which is extended from DbMigrationsConfiguration<YourContext>
internal sealed class Configuration : DbMigrationsConfiguration<YourContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
ContextKey = "YourContext_";
}
protected override void Seed(YourContext context)
{
//Migrate your data
}
}

Hooking IDbInterceptor to EntityFramework DbContext only once

The IDbCommandInterceptor interface is not very well documented. And I've only found a few scarce tutorials on it:
http://www.entityframeworktutorial.net/entityframework6/database-command-interception.aspx
https://msdn.microsoft.com/en-us/data/jj556606%28v=vs.113%29.aspx
https://entityframework.codeplex.com/wikipage?title=Interception
https://www.tutorialspoint.com/entity_framework/entity_framework_command_interception.htm
https://msdn.microsoft.com/en-us/data/dn469464%28v=vs.113%29.aspx
And a few SO questions:
Entity Framework 6 - Timing queries
Getting DbContext from implementation of IDbCommandInterceptor
These are the suggestions on hooking I've found:
1 - The static DbInterception class:
DbInterception.Add(new MyCommandInterceptor());
2 - Doing the above suggestion in a DbConfiguration class
public class MyDBConfiguration : DbConfiguration {
public MyDBConfiguration() {
DbInterception.Add(new MyCommandInterceptor());
}
}
3 - Using the config file:
<entityFramework>
<interceptors>
<interceptor type="EFInterceptDemo.MyCommandInterceptor, EFInterceptDemo"/>
</interceptors>
</entityFramework>
Although I couldn't figure out how to hook the DbConfiguration class to the DbContext, and neither what to put in the type part of the config method. Another example I found seemed to suggest that you write the namespace of a logger:
type="System.Data.Entity.Infrastructure.Interception.DatabaseLogger, EntityFramework"
I noted that DataBaseLogger implements IDisposable, IDbConfigurationInterceptor and
IDbInterceptor. IDbCommandInterceptor also implements IDbInterceptor, so I tried (without success) to format it like this:
type="DataLayer.Logging.MyCommandInterceptor, DataLayer"
And when I called the static DbInterception class directly, it added another interceptor every call. So my quick and dirty solution was to utilize static constructors:
//This partial class is a seperate file from the Entity Framework auto-generated class,
//to allow dynamic connection strings
public partial class MyDbContext // : DbContext
{
public Guid RequestGUID { get; private set; }
public MyDbContext(string nameOrConnectionString) : base(nameOrConnectionString)
{
DbContextListeningInitializer.EnsureListenersAdded();
RequestGUID = Guid.NewGuid();
//Database.Log = m => System.Diagnostics.Debug.Write(m);
}
private static class DbContextListeningInitializer
{
static DbContextListeningInitializer() //Threadsafe
{
DbInterception.Add(new MyCommandInterceptor());
}
//When this method is called, the static ctor is called the first time only
internal static void EnsureListenersAdded() { }
}
}
But what are the proper/intended ways to do it?
I figured out that my DbContext class just needed to have the DbConfigurationType attribute, to attach a configuration at runtime:
[DbConfigurationType(typeof(MyDBConfiguration))]
public partial class MyDbContext // : DbContext
{
public MyDbContext(string nameOrConnectionString) : base(nameOrConnectionString)
{ }
}
public class MyDBConfiguration : DbConfiguration {
public MyDBConfiguration() {
this.AddInterceptor(new MyCommandInterceptor());
}
}
The docs suggests that you can just put it in Application_Start:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
DbInterception.Add(new SchoolInterceptorTransientErrors());
DbInterception.Add(new SchoolInterceptorLogging());
}
The important part is that it only get's called once.

How to use an internal DbContext?

How to use an internal DbContext?
I wonder how can I hide the DbContext object so that other libraries of my project not directly access.
I put my DbContext as internal in the library, and apparently should work, however when I run the application, the following error appears:
The target context 'Context' is not constructible. Add a default constructor or Provide an Implementation of IDbContextFactory
Could someone help me?
My implementation of data layer is:
[DbConfigurationType(typeof (ConfigContext))]
internal class Context : DbContext
{
internal Context()
: base(ConfigDataBase.GetSqlServerString(ConfigZnfce.Instance.SqlServerInstance))
{
}
//More code below
}
public class ConfigContext: DbConfiguration
{
public ConfigContext()
{
SetDefaultConnectionFactory(new System.Data.Entity.Infrastructure.LocalDbConnectionFactory("v11.0"));
SetProviderServices("System.Data.SqlClient", System.Data.Entity.SqlServer.SqlProviderServices.Instance);
SetDatabaseInitializer(new CreateDatabaseIfNotExists<Context>());
SetDatabaseInitializer(new MigrateDatabaseToLatestVersion<Context, Configuration>());
}
}
I want all the other libraries are required to go through a unit of work and repositories in order to do any operation with the database
[SOLVED]
I left the Context class as "internal" and set the constructor as "public" as in the code below:
[DbConfigurationType(typeof (ConfigContext))]
internal class Context : DbContext
{
public Context()
: base(ConfigDataBase.GetSqlServerString(ConfigZnfce.Instance.SqlServerInstance))
{
}
//More code below
}
The virtual DBSet<> properties on the DbContext class must be public (as you found out in your solution.
If you're using TT templates, you can make this happen by changing the DbSet(EntitySet entitySet) function. Notice that the term public replaces the original {0} parameter in the string format.
public string DbSet(EntitySet entitySet) {
return string.Format(
CultureInfo.InvariantCulture,
"public virtual DbSet<{0}> {1} {{ get; set; }}",
_typeMapper.GetTypeName(entitySet.ElementType),
_code.Escape(entitySet));
}
Now, you can have an internal DbContext, internal objects, and still have the public automatic properties so EF can do its data-binding.

How to Unit Test with Dynamically-Generated ADO.NET Entity Data Model Code

I'm following this tutorial which explains how to mock the entity framework when performing unit testing on a Web API 2 service.
The code works by using dependency injection by defining an interface
namespace StoreAcreTransmissions.Models
{
public interface IStoreAcreTransmissionsContext : IDisposable
{
DbSet<AcreReportTransaction> AcreReportTransactions { get; }
int SaveChanges();
void MarkAsModified(AcreReportTransaction item);
}
}
that is then implemented by a class
namespace StoreAcreTransmissions.Models
{
public class StoreAcreTransmissionsContext : DbContext, IStoreAcreTransmissionsContext
{
// You can add custom code to this file. Changes will not be overwritten.
//
// If you want Entity Framework to drop and regenerate your database
// automatically whenever you change your model schema, please use data migrations.
// For more information refer to the documentation:
// http://msdn.microsoft.com/en-us/data/jj591621.aspx
public StoreAcreTransmissionsContext() : base("name=StoreAcreTransmissionsContext")
{
}
public System.Data.Entity.DbSet<StoreAcreTransmissions.Models.AcreReportTransaction> AcreReportTransactions { get; set; }
public void MarkAsModified(AcreReportTransaction item)
{
Entry(item).State = EntityState.Modified;
}
}
}
and passed to the constructor of the Controller
public AcreReportTransactionsController(IStoreAcreTransmissionsContext context)
{
db = context;
}
All this works great, but in the normal operation of the service I'm utilizing an auto-generated ADO Entity Data Model to communicate with the database. So in order for me to use the actual Data Model in my controller, I have to set it in the default constructor:
private IStoreAcreTransmissionsContext db;
public AcreReportTransactionsController()
{
db = new DataModelContext();
}
But I also have to modify the dynamically generated context class (AcreReportTransactionModel.Context.cs) that is generated by the model so that it also implements the IStoreAcreTransmissionsContext interface:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace StoreAcreTransmissions.Models
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class ACRSIEntities : DbContext, IStoreAcreTransmissionsContext
{
public ACRSIEntities()
: base("name=ACRSIEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<AcreReportTransaction> AcreReportTransactions { get; set; }
public void MarkAsModified(AcreReportTransaction item)
{
Entry(item).State = EntityState.Modified;
}
}
}
The problem is, every time I re-sync my model with the database, this dynamically-generated context class is re-created and the code I added to implement the IStoreAcreTransmissionsContext interface is removed.
How can I configure my code such that the unit tests work and I can re-generate my model without having to re-add code?
You shouldn't modify the generated code. Modify the template used to generate the code.
In the Solution Explorer open the tree of your EDMX-Model, here you find a file named *.Context.tt, open it and modify the appropriate section.
You can see that the generated context class includes the partial keyword. This means you can, in a new file, declare the following:
public partial class ACRSIEntities : IStoreAcreTransmissionsContext {
// Implement missing methods
public void MarkAsModified(AcreReportTransaction item)
{
Entry(item).State = EntityState.Modified;
}
}
There is more on partial classes in MSDN

Entity Framework : Change connection string at runtime

Assuming there is an ASP.NET MVC application that uses Entity Framework 6 with a code-first approach and StructureMap as IoC.
It also uses the Unit Of Work pattern.
Domain Class:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
IUnitOfWork and DbContext:
public interface IUnitOfWork
{
IDbSet<TEntity> Set<TEntity>() where TEntity : class;
int SaveChanges();
}
public class Sample07Context : DbContext, IUnitOfWork
{
public DbSet<Product> Products { set; get; }
#region IUnitOfWork Members
public new IDbSet<TEntity> Set<TEntity>() where TEntity : class
{
return base.Set<TEntity>();
}
#endregion
}
Business logic in service classes :
public interface IProductService
{
void AddNewProduct(Product product);
IList<Product> GetAllProducts();
}
public class ProductService: IProductService
{
IUnitOfWork _uow;
IDbSet<Product> _products;
public ProductService(IUnitOfWork uow)
{
_uow = uow;
_products = _uow.Set<Product>();
}
public void AddNewProduct(Product product)
{
_products.Add(product);
}
public IList<Product> GetAllProducts()
{
return _products.Include(x => x.Category).ToList();
}
}
Injecting the service class in controller
public class HomeController : Controller
{
private IProductService _productService;
private IUnitOfWork _uow;
public HomeController(IUnitOfWork uow, IProductService productService)
{
_productService = productService;
_uow = uow;
}
[HttpGet]
public ActionResult Index()
{
var list = _productService.GetAllProducts();
return View(list);
}
}
StructureMap Configuration that we call in app_start :
private static void initStructureMap()
{
ObjectFactory.Initialize(x =>
{
x.For<IUnitOfWork>().HttpContextScoped().Use(() => new Sample07Context());
x.ForRequestedType<IProductService>().TheDefaultIsConcreteType<EfProductService>();
});
//Set current Controller factory as StructureMapControllerFactory
ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
}
Everything works fine with the single database but in my scenario user can use multiple databases, I mean the user should be able to change the connection string at runtime. We create a separate database for each project that the user creates in the application.
Now the problem is that we inject DbContext into the service and DbContext reads the connection string from the web.config so when user changes the database we cannot set a new connection string to the DbContext.
What do you suggest?
In my experience, I used the Database First mode in EF 6. The DbContext would be generated like below when I add Entity Data Model.
public TestEntities()
: base("name=TestEntities")
{
}
The TestEntities represent the ConnectionString element in the App.Config
<connectionStrings>
<add name="TestEntities" connectionString="..." providerName="System.Data.EntityClient" />
</connectionStrings>
But you can change the default code to below.
public partial class TestEntities : DbContext
{
public TestEntities()
: base("name=TestEntities")
{
}
public TestEntities(string sConnectionString)
: base(sConnectionString)
{
}
...}
So you got two options to getting DB connection.
using the default. The EF will find the connection string in the config file.
passing the connection string to DbContext.
The code look like below.
EntityConnection entityConn =DBConnectionHelper.BuildConnection();
using (var db = new TestEntities(entityConn.ConnectionString))
{
....
}
As to the question How to build a EntityConnection?. Please see MSDN EntityConnection.
Hope it is helpful.
Thanks.
By default the name of the connection string to use in Entity Framework is inferred from the name of you DbContext class. However you can pass the connection string as a constructor parameter:
public class MyDbContext : DbContext, IUnitOfWork
{
public MyDbContext(string connectionString)
: base(connectionString)
{
}
}
Then you can configure StructureMap to pass in the current connection string e.g.
For<IUnitOfWork>().Use(ctx => new MyDbContext(TheConnectionStringToUse));
This could come from a static value that you set in your code, the current session etc.
I am going to suggest a completely different path. Assuming you have your connection strings set up in your web.config, which you say you do, why wouldn't you use web.debug.config and web.release.config transforrms to set your connection strings appropriately?
i.e. in web.debug.config
<connectionStrings>
<add name="FooEntities" connectionString="metadata=res://*/;provider=System.Data.SqlClient;provider connection string="Data Source=IP,PORT\Instancename;
Initial Catalog=Foo;Persist Security Info=True;User ID=admin;Password=password;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient"/>
</connectionStrings>
and a web.release.config as such
<connectionStrings xdt:Transform="Replace">
<add name="FooEntities" connectionString="metadata=res://*/;provider=System.Data.SqlClient;provider connection string="Data Source=LIVEIP,PORT\Instancename;
Initial Catalog=Foo;Persist Security Info=True;User ID=admin;Password=password;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient"/>
</connectionStrings>
A very thorough explanation is available here
public partial class YourDBContextClass
{
// Add a constructor to allow the connection string name to be changed
public YourDBContextClass(string connectionStringNameInConfig)
: base("name=" + connectionStringNameInConfig)
{
}
}
Add multiple connection strings to your web or app.config file.
in your program code:
YourDBContextClass dbcontext = new YourDBContextClass("alternateconnectionstringname");
The two approaches are good for two different situations:
The transform is good for deploying a connection string that only changes for the different evironments (test, production).
The approach of adding a constructor (which takes the connection string name) in a separate file to extend the partial dbcontext class allows the connection to be switched at runtime.
Add two different Connection String in App.Config File using different Name.
Set Current connection String Name in Entity Constructor using Overloading.
In Code File
public ASM_DBEntities()
: base("name=ASM_DBEntities")
{
}
public ASM_DBEntities(string conn)
: base("name=ASM_DBEntities1")
{
}
When we pass string with object then is use different connection string.

Categories