Created
August 23, 2016 19:06
-
-
Save bengavin/e75d5759b4941176b4e51b742428bd15 to your computer and use it in GitHub Desktop.
Example Custom DbSet/DbContext
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Collections.ObjectModel; | |
using System.Data.Entity; | |
using System.Data.Entity.Infrastructure; | |
using System.Linq; | |
using System.Linq.Expressions; | |
using System.Threading; | |
using System.Threading.Tasks; | |
namespace CustomDbSetSample | |
{ | |
class Program | |
{ | |
public static void Main(string[] args) | |
{ | |
Console.WriteLine("Creating Local Database"); | |
var sample1 = new MySampleEntity { Name = "Sample 1" }; | |
var sample2 = new MySampleEntity { Name = "Sample 2" }; | |
var sample3 = new MySampleEntity { Name = "Other Sample 3" }; | |
using (var myDbContext = new MyDbContext($@"Data Source=(LocalDB)\MSSQLLocalDB;Database=SampleDatabase;Integrated Security=True")) | |
{ | |
myDbContext.Database.CreateIfNotExists(); | |
// Clean existing samples | |
myDbContext.Database.ExecuteSqlCommand(@" | |
IF EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'MySampleEntity') BEGIN | |
exec sp_executesql N'DELETE FROM MySampleEntity'; | |
END ELSE BEGIN | |
CREATE TABLE [dbo].[MySampleEntity] | |
( | |
[Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY, | |
[Name] NVARCHAR(255) NOT NULL | |
) | |
END"); | |
// put some entities into the database | |
myDbContext.SampleEntities.Add(sample1); | |
myDbContext.SampleEntities.Add(sample2); | |
myDbContext.SampleEntities.Add(sample3); | |
myDbContext.SaveChanges(); | |
} | |
using (var myDbContext = new MyDbContext($@"Data Source=(LocalDB)\MSSQLLocalDB;Database=SampleDatabase;Integrated Security=True")) | |
{ | |
// Run some queries | |
var queriedSample1 = myDbContext.SampleEntities.AsNoTracking().FirstOrDefault(s => s.Id == sample1.Id); | |
Console.WriteLine($"Found Sample 1 ({queriedSample1?.Id == sample1.Id})"); | |
var queriedSamples = myDbContext.SampleEntities.AsNoTracking().Where(s => s.Name.StartsWith("Sample")).ToList(); | |
Console.WriteLine($"Found {queriedSamples.Count} entities starting with 'Sample'"); | |
// Add some more | |
myDbContext.SampleEntities.Attach(sample1); | |
myDbContext.SampleEntities.Remove(sample1); | |
var newSample = myDbContext.SampleEntities.Add(new MySampleEntity { Name = "New Sample" }); | |
myDbContext.SaveChanges(); | |
Console.WriteLine($"Found {myDbContext.SampleEntities.Count(s => s.Name.StartsWith("Sample"))} entities starting with 'Sample'"); | |
Console.WriteLine($"Found New Sample with Id: {myDbContext.SampleEntities.FirstOrDefault(s => s.Name == "New Sample")?.Id}"); | |
} | |
Console.ReadLine(); | |
} | |
public class CustomDbSet<TEntity> : DbSet<TEntity>, IDbSet<TEntity> | |
where TEntity : class | |
{ | |
private readonly DbSet<TEntity> _internalSet; | |
public CustomDbSet(DbSet<TEntity> internalSet) | |
{ | |
_internalSet = internalSet; | |
} | |
public override ObservableCollection<TEntity> Local => _internalSet.Local; | |
IQueryProvider IQueryable.Provider => ((IDbSet<TEntity>)_internalSet).Provider; | |
Type IQueryable.ElementType => ((IDbSet<TEntity>)_internalSet).ElementType; | |
Expression IQueryable.Expression => ((IDbSet<TEntity>)_internalSet).Expression; | |
public override DbQuery<TEntity> AsNoTracking() | |
{ | |
return _internalSet.AsNoTracking(); | |
} | |
public override DbQuery<TEntity> Include(string path) | |
{ | |
return _internalSet.Include(path); | |
} | |
public override TEntity Add(TEntity entity) | |
{ | |
Console.WriteLine("Do fancy bits here"); | |
return _internalSet.Add(entity); | |
} | |
public override TEntity Attach(TEntity entity) | |
{ | |
return _internalSet.Attach(entity); | |
} | |
public override TEntity Create() | |
{ | |
return _internalSet.Create(); | |
} | |
public override TEntity Find(params object[] keyValues) | |
{ | |
return _internalSet.Find(keyValues); | |
} | |
public override TEntity Remove(TEntity entity) | |
{ | |
return _internalSet.Remove(entity); | |
} | |
public override TDerivedEntity Create<TDerivedEntity>() | |
{ | |
return _internalSet.Create<TDerivedEntity>(); | |
} | |
public override IEnumerable<TEntity> AddRange(IEnumerable<TEntity> entities) | |
{ | |
return _internalSet.AddRange(entities); | |
} | |
public override Task<TEntity> FindAsync(params object[] keyValues) | |
{ | |
return _internalSet.FindAsync(keyValues); | |
} | |
public override Task<TEntity> FindAsync(CancellationToken cancellationToken, params object[] keyValues) | |
{ | |
return _internalSet.FindAsync(cancellationToken, keyValues); | |
} | |
} | |
public class MySampleEntity | |
{ | |
public MySampleEntity() | |
{ | |
Id = Guid.NewGuid(); | |
} | |
public Guid Id { get; set; } | |
public string Name { get; set; } | |
} | |
public class MyDbContext : DbContext | |
{ | |
public MyDbContext(string connectionString) : base(connectionString) | |
{ | |
} | |
public IDbSet<MySampleEntity> SampleEntities { get; set; } | |
protected override void OnModelCreating(DbModelBuilder modelBuilder) | |
{ | |
modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention>(); | |
base.OnModelCreating(modelBuilder); | |
} | |
public override DbSet<TEntity> Set<TEntity>() | |
{ | |
return new CustomDbSet<TEntity>(base.Set<TEntity>()); | |
} | |
} | |
} | |
} |
Not sure how to help you there :)
Have you tried converting your query to fluent syntax vs. the inline sql syntax to see if that helps clarify what's going wrong? In the sample above, there's no reason to continuously execute the same query to get the entire list of collateral many times and attach it to each currency record, I suspect there's a missing join in there, or you'd be better off executing the collateral query once and just assigning the resulting collection to each child record.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A got the error Object reference not set to an instance of an object when executing
var facCurr = (from f in dbContext.FACILITY join c in dbContext.CURRENCY on f.CURRENCY_ID equals c.ID where f.AMND_STATE == "F" select new { f.ID, FAC_AMND_STATE = f.AMND_STATE, f.CURRENCY_ID, CURR_AMNND_STATE = c.AMND_STATE, facColl = (from fc in dbContext.FACILITY_COLLATERAL select new { fc.ID, fc.COLLATERAL_ID }).ToList() }).ToList();
but when I executed split query, I worked.