Unit testing methods using AddOrUpdate with Entity Framework 6 Repository - entity-framework

I've managed to Mock an Entity Framework dbcontext and dbset to allow for unit testing querying functions against a repository component.
I've been unable to perform a successful test against an a method using Entity Frameworks' AddOrUpdate() method. The error received is:
"Unable to call public, instance method AddOrUpdate on derived IDbSet type 'Castle.Proxies.DbSet`1Proxy'. Method not found."
Is it at all possible to test this?
private IRepository _Sut;
private Mock<DbSet<JobListing>> _DbSet;
private Mock<RecruitmentDb> _DbContext;
[SetUp]
public void Setup()
{
_DbContext = new Mock<RecruitmentDb>();
var JobsData = GenerateJobs().AsQueryable();
_DbSet = new Mock<DbSet<JobListing>>();
_DbSet.As<IQueryable<JobListing>>().Setup(x => x.Provider).Returns(JobsData.Provider);
_DbSet.As<IQueryable<JobListing>>().Setup(x => x.Expression).Returns(JobsData.Expression);
_DbSet.As<IQueryable<JobListing>>().Setup(x => x.ElementType).Returns(JobsData.ElementType);
_DbSet.As<IQueryable<JobListing>>().Setup(x => x.GetEnumerator()).Returns(JobsData.GetEnumerator());
_DbContext.Setup(x => x.JobListings).Returns(_DbSet.Object);
_Sut = new JobListingRepository(_DbContext.Object);
}
[Test]
public void Update_ChangedTitleProperty_UpdatedDetails()
{
var Actual = GenerateJobs().First();
var OriginalJob = Actual;
Actual.Title = "Newly Changed Title";
_Sut.Update(Actual);
Actual.Title.Should().NotBe(OriginalJob.Title);
Actual.Id.Should().Be(OriginalJob.Id);
}
private List<JobListing> GenerateJobs()
{
return new List<JobListing>
{
new JobListing{ Id = 1,
Title = "Software Developer",
ShortDescription = "This is the short description",
FullDescription = "This is the long description",
Applicants = new List<Applicant>(),
ClosingDate = DateTime.Now.AddMonths(5).Date},
new JobListing{
Id = 2,
Title = "Head Chef",
ShortDescription = "This is the short description",
FullDescription = "This is the long description",
Applicants = new List<Applicant>(),
ClosingDate = DateTime.Now.AddMonths(2).Date
},
new JobListing
{
Id = 3,
Title = "Chief Minister",
ShortDescription = "This is the short description",
FullDescription = "This is the long description",
Applicants = new List<Applicant>(),
ClosingDate = DateTime.Now.AddMonths(2).Date
}
};
}

The issue is because AddOrUpdate is an extension method. I overcame this issue by designing a wrapper. You can mock/stub the IAddOrUpdateHelper interface instead.
public class AddOrUpdateHelper : IAddOrUpdateHelper
{
public void AddOrUpdateEntity<TEntity>(DataContext db, params TEntity[] entities) where TEntity : class
{
db.Set<TEntity>().AddOrUpdate(entities);
}
}
public interface IAddOrUpdateHelper
{
void AddOrUpdateEntity<TEntity>(DataContext db, params TEntity[] entities) where TEntity : class;
}

Related

Memory Cache .Net Core Not Persisting Values

I have a .NET Core 2.1 application. In Startup.cs configuration method, I use:
services.AddDbContext<ApplicationDbContext>(options =
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
...
services.AddMemoryCache();
Then in my controller:
public class DropDownListController : Controller
{
private readonly ApplicationDbContext _context;
private readonly IMemoryCache _memoryCache;
private const string ProvidersCacheKey = "providers";
private const string AgenciesCacheKey = "agencies";
public DropDownListController(ApplicationDbContext context, IMemoryCache memoryCache )
{
_context = context;
_memoryCache = memoryCache;
}
}
and in the controller also, the method to get the dropdownlist:
public JsonResult GetProvider()
{
IEnumerable<DropDownListCode.NameValueStr> providerlist;
if (_memoryCache.TryGetValue(ProvidersCacheKey, out providerlist))
{
return Json(providerlist);
}
else
{
MemoryCacheEntryOptions cacheExpirationOptions = new MemoryCacheEntryOptions();
cacheExpirationOptions.AbsoluteExpiration = DateTime.Now.AddDays(30);
cacheExpirationOptions.Priority = CacheItemPriority.Normal;
DropDownListCode um = new DropDownListCode(_context);
var result = um.GetProviderList();
_memoryCache.Set(ProvidersCacheKey, result);
return Json(result);
}
}
When I set a breakpoint on the line:
return Json(providerlist);
I see the ProvidersCacheKey is in the _memoryCache, but it has no value.
What happened to the data?
When I do a Quick Watch on _memoryCache, I can see the DbContext object was destroyed. But how can that be, the code works fine but the cache object does not have the data I saved to it.
Any help would be appreciated.
The method to get providers is:
public IEnumerable<NameValueStr> GetProviderList()
{
var providerlist = (from a in _context.AgencyProvider
where a.Provider == a.AgencyId
select new NameValueStr
{
id = a.Provider,
name = a.Name
});
return providerlist.Distinct();
}
Adding "ToList()" in the calling method worked:
MemoryCacheEntryOptions cacheExpirationOptions = new MemoryCacheEntryOptions();
cacheExpirationOptions.AbsoluteExpiration = DateTime.Now.AddMinutes(30);
cacheExpirationOptions.Priority = CacheItemPriority.Normal;
DropDownListCode um = new DropDownListCode(_context);
var result = um.GetProviderList().ToList();
_memoryCache.Set(ProvidersCacheKey, result);
return Json(result);
All credit goes to Steve Py… Thank you sir!

Seed data to UserRole table .net core

I want to seed the default DB with an admin user before I start the project on .NET Core Default MVC application. The code is as below:
public void SeedDb(ApplicationDbContext Context, IServiceProvider ServiceProvider, IConfiguration Configuration)
{
if (Context.Users.Count() > 0) return;
var UserManager = ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
var ApplicationUser = new ApplicationUser()
{
Email = Configuration["Email"],
NormalizedEmail = Configuration["Email"],
LockoutEnabled = false,
NormalizedUserName = Configuration["Email"],
SecurityStamp = "579355dd - a64c - 498d - a0b5 - 9e55754c9109",
EmailConfirmed = true,
ConcurrencyStamp = null,
Id = "977ec1a5-1ae7-4658-952a-6b5dccd75a85",
PasswordHash ="",
PhoneNumber = "333333333333",
LockoutEnd = null,
AccessFailedCount = 1,
PhoneNumberConfirmed = true,
TwoFactorEnabled = false,
UserName = Configuration["Email"]
};
var Password = HashPassword(ApplicationUser, Configuration["Password"]);
if (VerifyHashedPassword(ApplicationUser, Password, Configuration["Password"]) == PasswordVerificationResult.Success)
{
ApplicationUser.PasswordHash = Password;
}
Context.Users.Add(ApplicationUser);
Context.SaveChanges();
var RoleManager = ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
string[] Roles = { "Admin", "Manager", "User" };
foreach (string RoleName in Roles) {
RoleManager.CreateAsync(new IdentityRole(RoleName));
}
var Admin = Context.Users.SingleOrDefault(m => m.Email == Configuration["Email"]);
var Role = Context.Roles.SingleOrDefault(m => m.Name == Configuration["Role"]);
IdentityUserRole<string> UserRole = new IdentityUserRole<string>() { UserId = Admin.Id, RoleId = Role.Id };
Context.UserRoles.Add(UserRole);
Context.SaveChanges();
}
Everything runs perfect except I can't seed the UserRole DB with Data. From DBContext I add IdentityUserRole entity and save the changes to DB. Although nothing passed under the DB. Any suggestion?
Create a class named StartupDbInitializer:
using System;
using System.Collections.Generic;
using System.Linq;
using Core.Entities;
using Microsoft.AspNetCore.Identity;
namespace Core.Startups
{
public class StartupDbInitializer
{
private const string AdminEmail = "admin#admin.com";
private const string AdminPassword = "StrongPasswordAdmin123!";
private static readonly List<IdentityRole> Roles = new List<IdentityRole>()
{
new IdentityRole {Name = "Admin", NormalizedName = "ADMIN", ConcurrencyStamp = Guid.NewGuid().ToString()}
};
public static void SeedData(ApplicationDbContext dbContext, UserManager<User> userManager)
{
dbContext.Database.EnsureCreated();
AddRoles(dbContext);
AddUser(dbContext, userManager);
AddUserRoles(dbContext, userManager);
}
private static void AddRoles(ApplicationDbContext dbContext)
{
if (!dbContext.Roles.Any())
{
foreach (var role in Roles)
{
dbContext.Roles.Add(role);
dbContext.SaveChanges();
}
}
}
private static async void AddUser(ApplicationDbContext dbContext, UserManager<User> userManager)
{
if (!dbContext.Users.Any())
{
var user = new User {
UserName = AdminEmail,
Email = AdminEmail,
IsEnabled = true,
EmailConfirmed = true,
};
await userManager.CreateAsync(user, AdminPassword);
}
}
private static void AddUserRoles(ApplicationDbContext dbContext, UserManager<User> userManager)
{
if (!dbContext.UserRoles.Any())
{
var userRole = new IdentityUserRole<string>
{
UserId = dbContext.Users.Single(r => r.Email == AdminEmail).Id,
RoleId = dbContext.Roles.Single(r => r.Name == "Admin").Id
};
dbContext.UserRoles.Add(userRole);
dbContext.SaveChanges();
}
}
}
}
Then call it in your Startup's Configure method:
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env,
ApplicationDbContext dbContext,
UserManager<User> userManager,
)
{
// rest of code...
StartupDbInitializer.SeedData(dbContext, userManager);
}
Above, I inject my DbContext and UserManager<T>.
Try this line... it must work.
ApplicationUser user = await _usermanager.FindByEmailAsync("your.email#mymail.com");
if (!await _usermanager.IsInRoleAsync(user, "Admin"))
{
await _usermanager.AddToRoleAsync(user, "Admin");
}
When you tried it and it works, change it to your config parameters if you prefer them. It's not that hard to get it to work, you have everything you need in UserManager and RoleManager classes.
I still say you have to check if the role exist in table before you insert it, I got all my roles populated every time I run the application before I added the check.
if ((await _roleManager.FindByNameAsync("Admin")) == null)
{
await _roleManager.CreateAsync(new IdentityRole { Name = "Admin" });
}

Using DbContext in MS unit test

I am not sure how to fit EF into my business logic tests. Let me give an example of how it works at runtime (no testing, regular application run):
Context.Set<T>.Add(instance);
When I add the entity using the above generic method, an instance is added to context, and EF fixes all the navigation properties behind the scenes. For example, if exists [instance.Parent] property, and [parent.Instances] collection property (1-to-many relationship), EF will automatically add the instance to parent.Instances collection behind the scenes.
My code depends on the [parent.Instances] collection, and if it is empty, it will fail. When I am writing unit tests using MS testing framework, how can I reuse the power of EF, so it can still do its behind-the-scenes job, but uaing the memory as data storage, and not the actual database? I am not really interested whether EF successfully added, modified or deleted something in the database, I am just interested in getting the EF magic on the in-memory sets.
I've been doing this with a mock DbContext and mock DbSet that I've created. They store test data in memory and allow you to do most of the standard things you can do on a DbSet.
Your code that acquires the DbContext initially will have to be changed so that it acquires a MockDbContext when it is running under unit test. You can determine if you are running under MSTest with the following code:
public static bool IsInUnitTest
{
get
{
return AppDomain.CurrentDomain.GetAssemblies()
.Any(assembly =>
assembly.FullName.StartsWith(
"Microsoft.VisualStudio.QualityTools.UnitTestFramework"));
}
}
Here is the code for MockDbContext:
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Core.Objects;
using System.Data.Entity.Infrastructure;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication5
{
// ProductionDbContext would be DbContext class
// generated by Entity Framework
public class MockDbContext: ProductionDbContext
{
public MockDbContext()
{
LoadFakeData();
}
// Entities (for which we'll provide MockDbSet implementation
// and test data)
public override DbSet<Account> Accounts { get; set; }
public override DbSet<AccountGenLink> AccountGenLinks { get; set; }
public override DbSet<AccountPermit> AccountPermits { get; set; }
public override DbSet<AcctDocGenLink> AcctDocGenLinks { get; set; }
// DbContext method overrides
private int InternalSaveChanges()
{
// Just return 0 in the mock
return 0;
}
public override int SaveChanges()
{
return InternalSaveChanges();
}
public override Task<int> SaveChangesAsync()
{
return Task.FromResult(InternalSaveChanges());
}
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken)
{
// Just ignore the cancellation token in the mock
return SaveChangesAsync();
}
private void LoadFakeData()
{
// Tables
Accounts = new MockDbSet<Account>(this);
Accounts.AddRange(new List<Account>
{
new Account
{
SSN_EIN = "123456789", CODE = "A", accttype = "CD",
acctnumber = "1", pending = false, BankOfficer1 = string.Empty,
BankOfficer2 = null, Branch = 0, type = "18", drm_rate_code = "18",
officer_code = string.Empty, open_date = new DateTime(2010, 6, 8),
maturity_date = new DateTime(2010, 11, 8), HostAcctActive = true,
EffectiveAcctStatus = "A"
},
new Account
{
SSN_EIN = "123456789", CODE = "A", accttype = "DD",
acctnumber = "00001234", pending = false, BankOfficer1 = "BCK",
BankOfficer2 = string.Empty, Branch = 0, type = "05", drm_rate_code = "00",
officer_code = "DJT", open_date = new DateTime(1998, 9, 14),
maturity_date = null, HostAcctActive = true,
EffectiveAcctStatus = "A"
},
new Account
{
SSN_EIN = "123456789", CODE = "A", accttype = "LN", acctnumber = "1",
pending = false, BankOfficer1 = "LMP", BankOfficer2 = string.Empty,
Branch = 0, type = "7", drm_rate_code = null, officer_code = string.Empty,
open_date = new DateTime(2001, 10, 24),
maturity_date = new DateTime(2008, 5, 2), HostAcctActive = true,
EffectiveAcctStatus = "A"
}
});
AccountGenLinks = new MockDbSet<AccountGenLink>(this);
AccountGenLinks.AddRange(new List<AccountGenLink>
{
// Add your test data here if needed
});
AccountPermits = new MockDbSet<AccountPermit>(this);
AccountPermits.AddRange(new List<AccountPermit>
{
// Add your test data here if needed
});
AcctDocLinks = new MockDbSet<AcctDocLink>(this);
AcctDocLinks.AddRange(new List<AcctDocLink>
{
new AcctDocLink { ID = 1, SSN_EIN = "123456789", CODE = "A", accttype = "DD",
acctnumber = "00001234", DocID = 50, DocType = 5 },
new AcctDocLink { ID = 25, SSN_EIN = "123456789", CODE = "6", accttype = "CD",
acctnumber = "1", DocID = 6750, DocType = 5 }
});
}
}
}
And here is the code for MockDbSet:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.Entity;
using System.Data.Entity.Core.Metadata.Edm;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication5
{
public sealed class MockDbSet<TEntity> : DbSet<TEntity>, IQueryable,
IEnumerable<TEntity>, IDbAsyncEnumerable<TEntity> where TEntity : class
{
public MockDbSet(MockDbContext context)
{
// Get entity set for entity
// Used when we figure out whether to generate
// IDENTITY values
EntitySet = ((IObjectContextAdapter) context).ObjectContext
.MetadataWorkspace
.GetItems<EntityContainer>(DataSpace.SSpace).First()
.BaseEntitySets
.FirstOrDefault(item => item.Name == typeof(TEntity).Name);
Data = new ObservableCollection<TEntity>();
Query = Data.AsQueryable();
}
private ObservableCollection<TEntity> Data { get; set; }
Type IQueryable.ElementType
{
get { return Query.ElementType; }
}
private EntitySetBase EntitySet { get; set; }
Expression IQueryable.Expression
{
get { return Query.Expression; }
}
IEnumerator IEnumerable.GetEnumerator()
{
return Data.GetEnumerator();
}
public override ObservableCollection<TEntity> Local
{
get { return Data; }
}
IQueryProvider IQueryable.Provider
{
get { return new MockDbAsyncQueryProvider<TEntity>(Query.Provider); }
}
private IQueryable Query { get; set; }
public override TEntity Add(TEntity entity)
{
GenerateIdentityColumnValues(entity);
Data.Add(entity);
return entity;
}
public override IEnumerable<TEntity> AddRange(IEnumerable<TEntity> entities)
{
foreach (var entity in entities)
Add(entity);
return entities;
}
public override TEntity Attach(TEntity entity)
{
return Add(entity);
}
public override TEntity Create()
{
return Activator.CreateInstance<TEntity>();
}
public override TDerivedEntity Create<TDerivedEntity>()
{
return Activator.CreateInstance<TDerivedEntity>();
}
public override TEntity Find(params object[] keyValues)
{
throw new NotSupportedException();
}
public override Task<TEntity> FindAsync(params object[] keyValues)
{
return FindAsync(CancellationToken.None, keyValues);
}
public override Task<TEntity> FindAsync(CancellationToken cancellationToken, params object[] keyValues)
{
throw new NotSupportedException();
}
private void GenerateIdentityColumnValues(TEntity entity)
{
// The purpose of this method, which is called when adding a row,
// is to ensure that Identity column values are properly initialized
// before performing the add. If we were making a "real" Entity Framework
// Add() call, this task would be handled by the data provider and the
// value(s) would then be propagated back into the entity. In the case
// of this mock, there is nothing that will do that, so we have to make
// this at-least token effort to ensure the columns are properly initialized.
// In SQL Server, an Identity column can be of one of the following
// data types: tinyint, smallint, int, bigint, decimal (with a scale of 0),
// or numeric (with a scale of 0); This method handles the integer types
// (the others are typically not used).
foreach (var member in EntitySet.ElementType.Members.ToList())
{
if (member.IsStoreGeneratedIdentity)
{
// OK, we've got a live one; do our thing.
//
// Note that we'll get the current value of the column and,
// if it is nonzero, we'll leave it alone. We do this because
// the test data in our mock DbContext provides values for the
// Identity columns and many of those values are foreign keys
// in other entities (where we also provide test data). We don't
// want to disturb any existing relationships defined in the test data.
Type columnDataType = null;
foreach (var metadataProperty in member.TypeUsage.EdmType.MetadataProperties.ToList())
{
if (metadataProperty.Name != "PrimitiveTypeKind")
continue;
switch ((PrimitiveTypeKind)metadataProperty.Value)
{
case PrimitiveTypeKind.SByte:
columnDataType = typeof(SByte);
break;
case PrimitiveTypeKind.Int16:
columnDataType = typeof(Int16);
break;
case PrimitiveTypeKind.Int32:
columnDataType = typeof(Int32);
break;
case PrimitiveTypeKind.Int64:
columnDataType = typeof(Int64);
break;
default:
throw new InvalidOperationException();
}
var identityColumnGetter = entity.GetType().GetProperty(member.Name).GetGetMethod();
var identityColumnSetter = entity.GetType().GetProperty(member.Name).GetSetMethod();
Int64 specifiedColumnValue = 0;
switch (columnDataType.Name)
{
case "SByte":
specifiedColumnValue = (SByte)identityColumnGetter.Invoke(entity, null);
break;
case "Int16":
specifiedColumnValue = (Int16)identityColumnGetter.Invoke(entity, null);
break;
case "Int32":
specifiedColumnValue = (Int32)identityColumnGetter.Invoke(entity, null);
break;
case "Int64":
specifiedColumnValue = (Int64)identityColumnGetter.Invoke(entity, null);
break;
}
if (specifiedColumnValue != 0)
break;
Int64 maxExistingColumnValue = 0;
switch (columnDataType.Name)
{
case "SByte":
foreach (var item in Local.ToList())
maxExistingColumnValue = Math.Max(maxExistingColumnValue, (SByte)identityColumnGetter.Invoke(item, null));
identityColumnSetter.Invoke(entity, new object[] { (SByte)(++maxExistingColumnValue) });
break;
case "Int16":
foreach (var item in Local.ToList())
maxExistingColumnValue = Math.Max(maxExistingColumnValue, (Int16)identityColumnGetter.Invoke(item, null));
identityColumnSetter.Invoke(entity, new object[] { (Int16)(++maxExistingColumnValue) });
break;
case "Int32":
foreach (var item in Local.ToList())
maxExistingColumnValue = Math.Max(maxExistingColumnValue, (Int32)identityColumnGetter.Invoke(item, null));
identityColumnSetter.Invoke(entity, new object[] { (Int32)(++maxExistingColumnValue) });
break;
case "Int64":
foreach (var item in Local.ToList())
maxExistingColumnValue = Math.Max(maxExistingColumnValue, (Int64)identityColumnGetter.Invoke(item, null));
identityColumnSetter.Invoke(entity, new object[] { (Int64)(++maxExistingColumnValue) });
break;
}
}
}
}
}
IDbAsyncEnumerator<TEntity> IDbAsyncEnumerable<TEntity>.GetAsyncEnumerator()
{
return new MockDbAsyncEnumerator<TEntity>(Data.GetEnumerator());
}
IEnumerator<TEntity> IEnumerable<TEntity>.GetEnumerator()
{
return Data.GetEnumerator();
}
public override TEntity Remove(TEntity entity)
{
Data.Remove(entity);
return entity;
}
public override IEnumerable<TEntity> RemoveRange(IEnumerable<TEntity> entities)
{
foreach (var entity in entities)
Remove(entity);
return entities;
}
public override DbSqlQuery<TEntity> SqlQuery(string sql, params object[] parameters)
{
throw new NotSupportedException();
}
}
internal class MockDbAsyncQueryProvider<TEntity> : IDbAsyncQueryProvider
{
internal MockDbAsyncQueryProvider(IQueryProvider queryProvider)
{
QueryProvider = queryProvider;
}
private IQueryProvider QueryProvider { get; set; }
public IQueryable CreateQuery(Expression expression)
{
return new MockDbAsyncEnumerable<TEntity>(expression);
}
public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
{
return new MockDbAsyncEnumerable<TElement>(expression);
}
public object Execute(Expression expression)
{
return QueryProvider.Execute(expression);
}
public TResult Execute<TResult>(Expression expression)
{
return QueryProvider.Execute<TResult>(expression);
}
public Task<object> ExecuteAsync(Expression expression, CancellationToken cancellationToken)
{
return Task.FromResult(Execute(expression));
}
public Task<TResult> ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken)
{
return Task.FromResult(Execute<TResult>(expression));
}
}
internal class MockDbAsyncEnumerable<T> : EnumerableQuery<T>, IDbAsyncEnumerable<T>, IQueryable<T>
{
public MockDbAsyncEnumerable(IEnumerable<T> enumerable)
: base(enumerable)
{
}
public MockDbAsyncEnumerable(Expression expression)
: base(expression)
{
}
IQueryProvider IQueryable.Provider
{
get { return new MockDbAsyncQueryProvider<T>(this); }
}
public IDbAsyncEnumerator<T> GetAsyncEnumerator()
{
return new MockDbAsyncEnumerator<T>(this.AsEnumerable().GetEnumerator());
}
IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator()
{
return GetAsyncEnumerator();
}
}
internal class MockDbAsyncEnumerator<T> : IDbAsyncEnumerator<T>
{
public MockDbAsyncEnumerator(IEnumerator<T> enumerator)
{
Enumerator = enumerator;
}
public void Dispose()
{
Enumerator.Dispose();
}
public T Current
{
get { return Enumerator.Current; }
}
object IDbAsyncEnumerator.Current
{
get { return Current; }
}
private IEnumerator<T> Enumerator { get; set; }
public Task<bool> MoveNextAsync(CancellationToken cancellationToken)
{
return Task.FromResult(Enumerator.MoveNext());
}
}
}
If you are using the EntityFramework-Reverse-POCO-Code-First-Generator from Simon Hughes, with its generated FakeContext, Jeff Prince's approach is still possible with some tweaking. The little difference here is we are using the partial class support and implementing the InitializePartial() methods in the FakeContext and FakeDbSet. The bigger difference is that the Reverse POCO FakeContext does not inherit from a DbContext, so we can't easily get the MetadataWorkspace to know which columns are identities. The answer is to create a 'real' context with a bogus connection string and use that to get the EntitySetBase for the FakeDbSet. This should be pasted inside the proper namespace of a new source file, renaming the context, and you shouldn't need to do anything further in the rest of your project.
/// <summary>
/// This code will set Identity columns to be unique. It behaves differently from the real context in that the
/// identities are generated on add, not save. This is inspired by https://stackoverflow.com/a/31795273/1185620 and
/// modified for use with the FakeDbSet and FakeContext that can be generated by EntityFramework-Reverse-POCO-Code-
/// First-Generator from Simon Hughes.
///
/// Aside from changing the name of the FakeContext and the type used to in its InitializePartial() as
/// the 'realContext' this file can be pasted into another namespace for a completely unrelated context. If you
/// have additional implementation for the InitializePartial methods in the FakeContext or FakeDbSet, change the
/// name to InitializePartial2 and they will be called after InitializePartial is called here. Please don't add
/// code unrelated to the above purpose to this file - make another file to further extend the partial class.
/// </summary>
partial class FakeFooBarBazContext
{
/// <summary> Initialization of FakeContext to handle setting an identity for columns marked as
/// <c>IsStoreGeneratedIdentity</c> when an item is Added to the DbSet. If this signature
/// conflicts with another partial class, change that signature to implement
/// <see cref="InitializePartial2"/>, as that will be called when this is complete. </summary>
partial void InitializePartial()
{
// Here we need to get a 'real' ObjectContext so we can get the metadata for determining
// identity columns. Since FakeContext doesn't inherit from DbContext, create
// the real one with a bogus connection string.
using (var realContext = new FooBarBazContext("Server=."))
{
var objectContext = (realContext as IObjectContextAdapter).ObjectContext;
// Reflect over the public properties that return DbSet<> and get it. If it is
// of type FakeDbSet<>, call InitializeWithContext() on it.
var fakeDbSetGenericType = typeof(FakeDbSet<>);
var dbSetGenericType = typeof(DbSet<>);
var properties = this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var prop in properties)
{
if (!prop.PropertyType.IsGenericType || prop.GetMethod == null)
continue;
if (prop.PropertyType.GetGenericTypeDefinition() != dbSetGenericType)
continue;
var dbSetObj = prop.GetMethod.Invoke(this, null);
var dbSetObjType = dbSetObj?.GetType();
if (dbSetObjType?.GetGenericTypeDefinition() != fakeDbSetGenericType)
continue;
var initMethod = dbSetObjType.GetMethod(nameof(FakeDbSet<object>.InitializeWithContext),
BindingFlags.NonPublic | BindingFlags.Instance,
null, new[] {typeof(ObjectContext)}, new ParameterModifier[] { });
initMethod.Invoke(dbSetObj, new object[] {objectContext});
}
}
InitializePartial2();
}
partial void InitializePartial2();
}
partial class FakeDbSet<TEntity>
{
private EntitySetBase EntitySet { get; set; }
/// <summary> Initialization of FakeDbSet to handle setting an identity for columns marked as
/// <c>IsStoreGeneratedIdentity</c> when an item is Added to the DbSet. If this signature
/// conflicts with another partial class, change that signature to implement
/// <see cref="InitializePartial2"/>, as that will be called when this is complete. </summary>
partial void InitializePartial()
{
// The only way we know something was added to the DbSet from this partial class
// is to hook the CollectionChanged event.
_data.CollectionChanged += DataOnCollectionChanged;
InitializePartial2();
}
internal void InitializeWithContext(ObjectContext objectContext)
{
// Get entity set for entity. Used when we figure out whether to generate IDENTITY values
EntitySet = objectContext
.MetadataWorkspace
.GetItems<EntityContainer>(DataSpace.SSpace).First()
.BaseEntitySets
.FirstOrDefault(item => item.Name == typeof(TEntity).Name);
}
private void DataOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action != NotifyCollectionChangedAction.Add)
return;
foreach (TEntity entity in e.NewItems)
GenerateIdentityColumnValues(entity);
}
/// <summary> The purpose of this method, which is called after a row is added, is to ensure that Identity column values are
/// properly initialized. If this was a real Entity Framework, this task would be handled by the data provider
/// when SaveChanges[Async]() is called and the value(s) would then be propagated back into the entity.
/// In the case of FakeDbSet, there is nothing that will do that, so we have to make this at-least token effort
/// to ensure the columns are properly initialized, even if it is done at the incorrect time.
/// </summary>
private void GenerateIdentityColumnValues(TEntity entity)
{
foreach (var member in EntitySet.ElementType.Members)
{
if (!member.IsStoreGeneratedIdentity)
continue;
foreach (var metadataProperty in member.TypeUsage.EdmType.MetadataProperties)
{
if (metadataProperty.Name != "PrimitiveTypeKind")
continue;
var entityProperty = entity.GetType().GetProperty(member.Name);
var identityColumnGetter = entityProperty.GetGetMethod();
// Note that we'll get the current value of the column and,
// if it is nonzero, we'll leave it alone. We do this because
// the test data in our mock DbContext provides values for the
// Identity columns and many of those values are foreign keys
// in other entities (where we also provide test data). We don't
// want to disturb any existing relationships defined in the test data.
bool isDefaultForType;
var columnType = (PrimitiveTypeKind)metadataProperty.Value;
switch (columnType)
{
case PrimitiveTypeKind.SByte:
isDefaultForType = default(SByte) == (SByte)identityColumnGetter.Invoke(entity, null);
break;
case PrimitiveTypeKind.Int16:
isDefaultForType = default(Int16) == (Int16)identityColumnGetter.Invoke(entity, null);
break;
case PrimitiveTypeKind.Int32:
isDefaultForType = default(Int32) == (Int32)identityColumnGetter.Invoke(entity, null);
break;
case PrimitiveTypeKind.Int64:
isDefaultForType = default(Int64) == (Int64)identityColumnGetter.Invoke(entity, null);
break;
case PrimitiveTypeKind.Decimal:
isDefaultForType = default(Decimal) == (Decimal)identityColumnGetter.Invoke(entity, null);
break;
default:
// In SQL Server, an Identity column can be of one of the following data types:
// tinyint (SqlByte, byte), smallint (SqlInt16, Int16), int (SqlInt32, Int32),
// bigint (SqlInt64, Int64), decimal (with a scale of 0) (SqlDecimal, Decimal),
// or numeric (with a scale of 0) (SqlDecimal, Decimal). Those are handled above.
// 'If we don't know, we throw'
throw new InvalidOperationException($"Unsupported Identity Column Type {columnType}");
}
// From this point on, we can return from the method, as only one identity column is
// possible per table and we found it.
if (!isDefaultForType)
return;
var identityColumnSetter = entityProperty.GetSetMethod();
lock (Local)
{
switch (columnType)
{
case PrimitiveTypeKind.SByte:
{
SByte maxExistingColumnValue = 0;
foreach (var item in Local.ToList())
maxExistingColumnValue = Math.Max(maxExistingColumnValue, (SByte) identityColumnGetter.Invoke(item, null));
identityColumnSetter.Invoke(entity, new object[] {(SByte) (++maxExistingColumnValue)});
return;
}
case PrimitiveTypeKind.Int16:
{
Int16 maxExistingColumnValue = 0;
foreach (var item in Local.ToList())
maxExistingColumnValue = Math.Max(maxExistingColumnValue, (Int16) identityColumnGetter.Invoke(item, null));
identityColumnSetter.Invoke(entity, new object[] {(Int16) (++maxExistingColumnValue)});
return;
}
case PrimitiveTypeKind.Int32:
{
Int32 maxExistingColumnValue = 0;
foreach (var item in Local.ToList())
maxExistingColumnValue = Math.Max(maxExistingColumnValue, (Int32) identityColumnGetter.Invoke(item, null));
identityColumnSetter.Invoke(entity, new object[] {(Int32) (++maxExistingColumnValue)});
return;
}
case PrimitiveTypeKind.Int64:
{
Int64 maxExistingColumnValue = 0;
foreach (var item in Local.ToList())
maxExistingColumnValue = Math.Max(maxExistingColumnValue, (Int64) identityColumnGetter.Invoke(item, null));
identityColumnSetter.Invoke(entity, new object[] {(Int64) (++maxExistingColumnValue)});
return;
}
case PrimitiveTypeKind.Decimal:
{
Decimal maxExistingColumnValue = 0;
foreach (var item in Local.ToList())
maxExistingColumnValue = Math.Max(maxExistingColumnValue, (Decimal) identityColumnGetter.Invoke(item, null));
identityColumnSetter.Invoke(entity, new object[] {(Decimal) (++maxExistingColumnValue)});
return;
}
}
}
}
}
}
partial void InitializePartial2();
}

How to connect Devexpress scheduler with a custom data table

DataSet1 ds1 = new DataSet1();
ds1.tblSchedul.Rows.Add(0, "t_test", "4/10/2013 11:30:00 AM", "0", "D", "", "", "", "4/10/2013 8:15:45 AM", "2", "sub", "0");
tblSchedulBindingSource.DataSource = ds1.tblSchedul;
But it is not working. Whats the possible solution ??
using System.Threading;
using System.Text.RegularExpressions;
using System.Data.Odbc;
using DevExpress.XtraEditors.Controls;
using DevExpress.XtraEditors;
namespace Project
{
public partial class frmSchedule : Form
{
DataSet scheduleDataset;
SQLConnection scheduleConn;
SQLDataAdapter scheduleAdapter;
private void Form1_Load(object sender, EventArgs e)
{
schedulerControl1.Start = DateTime.Now;
scheduleDataset = new DataSet();
scheduleConn = objconnection.getConnection();// DatabaseConnection
scheduleConn.Open();
fillData("SELECT * FROM table_name");
}
private void fillData(string query)
{
scheduleDataset = new DataSet();
scheduleAdapter = new SQLDataAdapter(query, scheduleConn);
scheduleAdapter.RowUpdated += new SQLRowUpdatedEventHandler(scheduleAdapter_RowUpdated);
scheduleAdapter.Fill(scheduleDataset, "table_name");
this.appointmentsBS.DataSource = scheduleDataset;
this.appointmentsBS.DataMember = "table_name";
this.appointmentsBS.Position = 0;
this.schedulerStorage1.Appointments.DataSource = this.appointmentsBS;
this.schedulerStorage1.Appointments.Mappings.field1= "Field1";
this.schedulerStorage1.Appointments.Mappings.Field2= "Field2";
AppointmentCustomFieldMapping IDD = new AppointmentCustomFieldMapping("IDD", "IDD");
schedulerStorage1.Appointments.CustomFieldMappings.Add(IDD);
SQLCommandBuilder cmdBuilder = new SQLCommandBuilder(scheduleAdapter);
scheduleAdapter.InsertCommand = cmdBuilder.GetInsertCommand();
scheduleAdapter.DeleteCommand = cmdBuilder.GetDeleteCommand();
scheduleAdapter.UpdateCommand = cmdBuilder.GetUpdateCommand();
}
}
}
You need to use Appointments Mapping for the database tabel .
first , load the database tabel in DataTabel and use mapping method to maps the fields .
try looking at this code : Devexpress Mapping

Proper way to profile a DbContext using MiniProfiler and EF 5 and Autofac

The MiniProfiler site gives the following code for generating an Entity Framework ObjectContext:
public static MyModel Get()
{
var conn = new StackExchange.Profiling.Data.EFProfiledDbConnection(GetConnection(), MiniProfiler.Current);
return ObjectContextUtils.CreateObjectContext<MyModel>(conn); // resides in the MiniProfiler.EF nuget pack
}
However, using Entity Framework 5, I am not using an ObjectContext - rather I am using a DbContext. I cannot plug the model name in here, since the CreateObjectContext<T>() method expects T to be of type ObjectContext. (For the same reason, the code given in this answer also doesn't work).
Additionally, I am using autofac to initialize my Db connections. This is being registered with the following (MyData = the name of my EF DataContext):
Builder.RegisterType<MyData>().As<DbContext>().InstancePerHttpRequest();
So combining two parts: how can I use autofac to initialize my DbContext tied into MiniProfiler.EF? And if that is not possible, at least how can I do the first part (create a factory method for MiniProfiler.EF to return a DbContext)?
I just got this working:
public static class DbContextUtils
{
private const BindingFlags PrivateInstance = BindingFlags.NonPublic | BindingFlags.Instance;
public static T CreateDbContext<T>() where T : DbContext
{
return CreateDbContext<T>(GetProfiledConnection<T>());
}
public static T CreateDbContext<T>(this DbConnection connection) where T : DbContext
{
var workspace = new MetadataWorkspace(new[] { "res://*/" }, new[] { typeof(T).Assembly });
var factory = DbProviderServices.GetProviderFactory(connection);
var itemCollection = workspace.GetItemCollection(DataSpace.SSpace);
var providerFactoryField = itemCollection.GetType().GetField("_providerFactory", PrivateInstance);
if (providerFactoryField != null) providerFactoryField.SetValue(itemCollection, factory);
var ec = new EntityConnection(workspace, connection);
return CtorCache<T, DbConnection>.Ctor(ec);
}
public static DbConnection GetProfiledConnection<T>() where T : DbContext
{
var dbConnection = ObjectContextUtils.GetStoreConnection("name=" + typeof(T).Name);
return new EFProfiledDbConnection(dbConnection, MiniProfiler.Current);
}
internal static class CtorCache<TType, TArg> where TType : class
{
public static readonly Func<TArg, TType> Ctor;
static CtorCache()
{
var argTypes = new[] { typeof(TArg) };
var ctor = typeof(TType).GetConstructor(argTypes);
if (ctor == null)
{
Ctor = x => { throw new InvalidOperationException("No suitable constructor defined"); };
}
else
{
var dm = new DynamicMethod("ctor", typeof(TType), argTypes);
var il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Newobj, ctor);
il.Emit(OpCodes.Ret);
Ctor = (Func<TArg, TType>)dm.CreateDelegate(typeof(Func<TArg, TType>));
}
}
}
}
It is based on the code in MiniProfiler's ObjectContextUtils.
You use it like this:
builder.Register(c => DbContextUtils.CreateDbContext<MyData>()).As<DbContext>().InstancePerHttpRequest();
This solution REQUIRES your DbContext to have a constructor which takes a DbConnection and passes it to base, like this:
public MyData(DbConnection connection)
: base(connection, true)
{
}
There is a constructor of the DbContext class which takes an existing DbConnection
So you need a new contructor on your MyData which just calls the base
public class MyData : DbContext
{
public MyData(DbConnection existingConnection, bool contextOwnsConnection)
: base(existingConnection, contextOwnsConnection)
{
}
//..
}
Then you register your MyData with Register:
builder.Register(c =>
{
var conn = new EFProfiledDbConnection(GetConnection(), MiniProfiler.Current);
return new MyData(conn, true);
}).As<DbContext>().InstancePerHttpRequest();