I have the following Repository Pattern. Requirement is to “Find All accounts whose owner’s name is Lijo”. So, I need to write a FindAll function. How to write this function?
Constraints are:
1) The client “BankAccountService” should not use classes from 'DBML_Project'.
2) We should NOT use GetAll method to retireve complete list of accounts and then do a filter.
Note: I confronted this problem while working on the question Polymorphism: Is ORM entity a Domain Entity or Data Entity?
CODE
namespace ApplicationService_Bank
{
public class BankAccountService
{
RepositoryLayer.ILijosBankRepository accountRepository = new RepositoryLayer.LijosSimpleBankRepository();
public void FreezeAllAccountsForUser(string userName)
{
//Should not use assembly 'DBML_Project'.
IEnumerable<DomainEntitiesForBank.IBankAccount> accountsForUserWithNameLIJO = null;
//accountsForUserWithNameLIJO = accountRepository.FindAll(p => p.BankUser.Name == "Lijo");
}
}
}
namespace RepositoryLayer
{
public interface ILijosBankRepository
{
List<DomainEntitiesForBank.IBankAccount> GetAll();
IEnumerable<DBML_Project.BankAccount> FindAll(System.Func<DBML_Project.BankAccount, bool> predicate);
void SubmitChanges();
}
public class LijosSimpleBankRepository : ILijosBankRepository
{
private IBankAccountFactory bankFactory = new MySimpleBankAccountFactory();
public System.Data.Linq.DataContext Context
{
get;
set;
}
public virtual List<DomainEntitiesForBank.IBankAccount> GetAll()
{
List<DBML_Project.BankAccount> allItems = Context.GetTable<DBML_Project.BankAccount>().ToList();
List<DomainEntitiesForBank.IBankAccount> bankAccounts = new List<DomainEntitiesForBank.IBankAccount>();
foreach (DBML_Project.BankAccount acc in allItems)
{
DomainEntitiesForBank.IBankAccount theAccount = bankFactory.CreateAccount(acc.AccountType, acc.BankAccountID, acc.Status, acc.OpenedDate, acc.AccountOwnerID);
bankAccounts.Add(theAccount);
}
return bankAccounts;
}
public IEnumerable<DBML_Project.BankAccount> FindAll(System.Func<DBML_Project.BankAccount, bool> predicate)
{
//Where
var results = Context.GetTable<DBML_Project.BankAccount>().Where(predicate);
return results;
}
public virtual void SubmitChanges()
{
Context.SubmitChanges();
}
}
}
READING:
Returning IEnumerable<T> vs. IQueryable<T>
how to design Repository pattern to be easy switch to another ORM later?
A simple approach is to just build the query by hand:
public class SearchCriteria
{
public string Name { get; set; }
// ...more
}
public IEnumerable<Entity> FindAll(SearchCriteria criteria)
{
IQueryable<Entity> entities = _datasource.Entities; // replace with your L2S equivalent
if (criteria.Name != null)
entities = entities.Where(e => e.Name == criteria.Name);
// ...more
return entities;
}
If you don't want to return the generated objects directly, map to something else before you return:
return Map(entities); // IEnumerable<CustomObject> Map(IEnumerable<Entity> entities)
Related
I use a similar approach to the one described in this post to map multiple stored procedure result sets to a parent and child entity using Entity Framework. However, every implementation of this approach that I've seen assigns the results of subsequent result sets (after the first) to properties of the parent entity directly; I'd like to accomplish this in a generic fashion.
So far I've been able to build a wrapper that successfully maps results in a one-to-many relationship. I don't need to care about enforcing the foreign key relationship in this case because the stored procedure handles that, but when selecting many parent entities, I need to somehow enforce the relationship.
How can I leverage the foreign key relationship in Entity Framework (using reflection, presumably) to enforce the mapping?
Here's what I have:
Entities
class FooEntity
{
[Key]
int Id { get; set;}
ICollection<BarEntity> Bars { get; set; }
}
class BarEntity
{
[Key]
int Id { get; set;}
int FooId { get; set; }
[ForeignKey("FooId")]
virtual FooEntity Foo { get; set; }
}
Generic stored procedure translator:
public class StoredProcedureTranslator<TDbContext> : IDisposable where TDbContext : DbContext, new()
{
private DbCommand command;
public StoredProcedureTranslator()
{
this.Context = new TDbContext();
}
public DbContext Context { get; set; }
public DbDataReader Reader { get; set; }
public StoredProcedureResult<T, TDbContext> Translate<T>(string procedureName, SqlParameter[] parameters) where T : class
{
this.command = this.Context.Database.Connection.CreateCommand();
this.command.CommandText = procedureName;
if (parameters != null)
{
this.command.Parameters.AddRange(parameters);
}
this.command.CommandType = CommandType.StoredProcedure;
this.Context.Database.Connection.Open();
this.Reader = this.command.ExecuteReader();
ObjectResult<T> results = ((IObjectContextAdapter)this.Context).ObjectContext.Translate<T>(this.Reader);
return new StoredProcedureResult<T, TDbContext>(results.ToList(), this);
}
public void Dispose()
{
this.Context.Dispose();
}
}
Generic stored procedure result:
public class StoredProcedureResult<T, TDbContext> : IEnumerable<T>
where T : class where TDbContext : DbContext, new()
{
private readonly IEnumerable<T> results;
private readonly StoredProcedureTranslator<TDbContext> translator;
public StoredProcedureResult(IEnumerable<T> results, StoredProcedureTranslator<TDbContext> translator)
{
this.results = results;
this.translator = translator;
}
public StoredProcedureResult<T, TDbContext> Include<TChild>(Expression<Func<T, IEnumerable<TChild>>> member) where TChild : class
{
T result = this.results.FirstOrDefault();
if (result == null)
{
return null;
}
if (!this.translator.Reader.NextResult())
{
return new StoredProcedureResult<T, TDbContext>(new List<T> { result }, this.translator);
}
// TODO: do some stuff with the fks
ObjectResult<TChild> childResults = ((IObjectContextAdapter)this.translator.Context).ObjectContext.Translate<TChild>(this.translator.Reader);
var prop = member.Body as MemberExpression;
if (prop == null)
{
throw new Exception("blah blah");
}
var property = prop.Member as PropertyInfo;
if (property == null)
{
throw new Exception("blah blah");
}
property.SetValue(result, childResults.ToList(), null);
return new StoredProcedureResult<T, TDbContext>(new List<T> { result }, this.translator);
}
#region IEnumerable Impl
public IEnumerator GetEnumerator()
{
return this.results.GetEnumerator();
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return (IEnumerator<T>)this.GetEnumerator();
}
#endregion
}
Usage
using (var spt = new StoredProcedureTranslator<DbContext>())
{
FooEntity foo = spt.Translate<FooEntity>("[dbo].[foo_get]", null).Include(f => f.Bars).FirstOrDefault();
}
If this is intended to be used for entity types only, you can let EF context tracking infrastructure and relationship fix up do the work for you (pretty match like the EF materializes entity queries).
The trick is to use the following Translate method overload
public virtual ObjectResult<TEntity> Translate<TEntity>(DbDataReader reader, string entitySetName, MergeOption mergeOption)
and pass the entitySetName of the entity type.
Here is small helper utility class which does that (plus some other useful methods):
public static class EntityUtils
{
public static string GetEntitySetName<T>(this IObjectContextAdapter dbContext) where T : class
{
return dbContext.ObjectContext.CreateObjectSet<T>().EntitySet.Name;
}
public static ObjectResult<T> ReadSingleResult<T>(this IObjectContextAdapter dbContext, DbDataReader dbReader)
where T : class
{
return dbContext.ObjectContext.Translate<T>(dbReader, dbContext.GetEntitySetName<T>(), MergeOption.AppendOnly);
}
public static void Load<T>(this ObjectResult<T> source) where T : class
{
// Consume the enumerable by iterating it
using (var en = source.GetEnumerator())
while (en.MoveNext()) { }
}
}
The StoredProcedureTranslator and StoredProcedureResult can be modified as follows (I find the design a bit flawed, but that's outside the scope of the question).
The result:
public class StoredProcedureResult<T> : IEnumerable<T>
where T : class
{
private readonly DbContext context;
private readonly DbDataReader reader;
private readonly IEnumerable<T> results;
public StoredProcedureResult(DbContext context, DbDataReader reader)
{
this.context = context;
this.reader = reader;
this.results = this.context.ReadSingleResult<T>(this.reader).ToList();
}
public StoredProcedureResult<T> Include<TChild>() where TChild : class
{
if (this.reader.NextResult())
this.context.ReadSingleResult<TChild>(this.reader).Load();
return this;
}
public IEnumerator<T> GetEnumerator()
{
return this.results.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
Note that it doesn't need TDbContext generic parameter anymore, and all it does is to hold the root result set while providing fluent interface for reading the next results. The results are just translated and consumed, there is no need to be stored because during the consuming part EF will bind them to the already loaded related entities.
The translate method inside the StoredProcedureTranslator class:
public StoredProcedureResult<T> Translate<T>(string procedureName, SqlParameter[] parameters) where T : class
{
this.command = this.Context.Database.Connection.CreateCommand();
this.command.CommandText = procedureName;
if (parameters != null)
this.command.Parameters.AddRange(parameters);
this.command.CommandType = CommandType.StoredProcedure;
this.Context.Database.Connection.Open();
this.Reader = this.command.ExecuteReader();
return new StoredProcedureResult<T>(this.Context, this.Reader);
}
Usage:
using (var spt = new StoredProcedureTranslator<DbContext>())
{
var foo = spt.Translate<FooEntity>("[dbo].[foo_get]", null)
.Include<BarEntity>()
.FirstOrDefault();
}
This is my first question here and i'm not very familliar with the C# terminology, so if i get some terms or definitions mixed up i appologize in advance.
I have set up a generic EF data access layer;
public class BaseService<TObject> where TObject : class
{
private DbContext Context;
private static readonly Lazy<BaseService<TObject>> lazy = new Lazy<BaseService<TObject>>(() => new BaseService<TObject>());
public static BaseService<TObject> Instance => lazy.Value;
public BaseService()
{
Context = new evEntities();
}
public BaseService(DbContext context)
{
Context = context;
}
public ICollection<TObject> GetAll()
{
return Context.Set<TObject>().ToList();
}
public async Task<ICollection<TObject>> GetAllAsync()
{
return await Context.Set<TObject>().ToListAsync();
}
public TObject Get(int id)
{
return Context.Set<TObject>().Find(id);
}
}
Together with this;
public static class DA
{
public static DataAccess.Categories Categories => new DataAccess.Categories();
public static DataAccess.Tags Tags => new DataAccess.Tags();
public static DataAccess.Users Users => new DataAccess.Users();
}
public static class DA<T> where T : class
{
public static BaseService<T> Base => new BaseService<T>();
}
So in my Business Layer i can do this;
public class Categories
{
public Categories() { }
public ICollection<Database.Categories> GetAll()
{
return DA.Categories.GetAll().ToList();
}
public async Task<ICollection<Database.Categories>> GetAllAsync()
{
return await DA.Categories.GetAllAsync();
}
public Database.Categories Get(int id)
{
return DA.Categories.Get(id);
}
}
For clarity. My EF creates classes/entities like 'Database.Categories' and 'Database.Users' which i pass as 'TObject' to my BaseService to get a standard way of pulling data from my database for all my entities.
Now my question. In a similar way i want to create a generic Business Layer. Like;
public class BusinessLogicBase<TModel>
{
public ICollection<TDBModel> GetAll()
{
return null;
}
public async Task<ICollection<TDBModel>> GetAllAsync()
{
return await DA.Categories.GetAllAsync();
}
public TDBModel Get(int id)
{
return DA.Categories.Get(id);
}
}
I want to be able to call the DA with a TObject like Database.Categories but this has to be dynamic, based on the type passed to the BusinessLogicBase. So i want to do something like this (which doesn't work);
private ???? DetermineDatabaseModel()
{
switch(typeof(TModell))
{
case Models.Categories:
return Database.Categories;
case Models.Users:
return Database.Users;
}
}
So i can do this;
public ICollection<TDBModel> GetAll()
{
var databaseModel = DetermineDatabaseModel()
return DA<databaseModel>().GetAll();
}
I hope you understand my question and can help me.
Thnx!
Sorry for the long post, and for all you 9gaggers, here's a potato... No just kidding, this is serious.
Have you tried something like:
public class BusinessLogicBase<TDBModel> where TDBModel : class {
public ICollection<TDBModel> GetAll() {
return DA<TDBModel>.Base.GetAll();
}
}
UPDATE 1:
Maybe it would help You if you try to write it without generics first and then convert it into more general pattern using generics. There are some missteps that are easier to solve without generics.
Method public ICollection<TDBModel> GetAll() can't return ICollection<TDBModel> because type parameter TDBModel is not defined either in class signature or method signature. I makes more sense if you define it like this:
public class BusinessLogicBase<TModel>
{
public ICollection<TModel> GetAll()
{
return null;
}
}
UPDATE 2:
try this simple console app to demonstrate dynamic keyword and watch what is stored in variables categories and users.
UPDATE 3:
Based on fiddle - I've changed IBaseService<dynamic> to dynamic:
public class BL<TModel>
{
// This is what i want to make dynamic.
// how do i create a return type that i can use in DA<>..
private Type testDetermineDatabaseModel()
{
switch(typeof(TModel).Name){
case "Categories":
return typeof(Database.Categories);
case "Users":
return typeof(Database.Users);
}
return null;
}
public ICollection<TModel> testGetAll()
{
var databaseModel = testDetermineDatabaseModel();
// return DA<databaseModel>().Base.GetAll();
return new List<TModel>();
}
// NEW
// I have constructed the following.
private dynamic baseService;
public dynamic DetermineDatabaseModel()
{
switch (typeof(TModel).Name)
{
case "Categories":
return new BaseService<Database.Categories>();
case "Users":
return new BaseService<Database.Users>();
default:
return null;
}
}
private IBaseService<TDbModel> GetBase<TDbModel>() where TDbModel : class
{
return new BaseService<TDbModel>();
}
public ICollection<TModel> GetAll()
{
ICollection<TModel> returnValue = new List<TModel>();
// This works!!!
foreach (var item in GetBase<Database.Categories>().GetAll())
{
returnValue.Add((TModel)(object)item);
}
baseService = DetermineDatabaseModel();
// This doesn't!!! It's the same thing!! :(
foreach (var item in baseService.GetAll())
{
returnValue.Add((TModel)(object)item);
}
return returnValue;
}
}
But remember, this not solve the issue You are facing. That is map 2 generic types.
I have just learned about GraphDiff, and how it is supposed to take care of all the differences between the disconnected entity and the one stored in the database.
The thing is that I do not know how to use GraphDiff, I tried the documentation, but I didn't understand it well.
I am using an abstracted DBContext, through an Interface and using DbSet so I could perform Unit Testing on them:
public interface IDbRepositories
{
IDbSet<Client> ClientsDB { get;}
AppIdentityDbContext DB { get; }
IDbSet<Contacts> ContactsDB { get; }
IDbSet<ExposureResult> ExposureDB { get; }
IDbSet<OrderMods> OrderModsDB { get; }
IDbSet<ProductDetails> ProductDetailsDB { get; }
IDbSet<OrderProcess> OrderProcessDB { get; }
IDbSet<Order> OrderDB { get; }
void SaveChanges();
}
This is the actual class implementing the interface:
public class DbRepositories : IDbRepositories
{
private AppIdentityDbContext db = new AppIdentityDbContext();
//Get DB Context. This is done this way, so a Mock can be injected when testing
public IDbSet<Client> ClientsDB
{
get { return db.Clients; }
}
public AppIdentityDbContext DB
{
get { return db; }
}
public IDbSet<Contacts> ContactsDB
{
get { return db.Contacts; }
}
public IDbSet<ExposureResult> ExposureDB
{
get { return db.ExposureTBL; }
}
public IDbSet<OrderMods> OrderModsDB
{
get { return db.OrderMods; }
}
public IDbSet<ProductDetails> ProductDetailsDB
{
get { return db.ProductDetailsTBL; }
}
public IDbSet<OrderProcess> OrderProcessDB
{
get { return db.OrderProcesses; }
}
public IDbSet<Order> OrderDB
{
get { return db.OrderTBL; }
}
public void SaveChanges()
{
this.db.SaveChanges();
}
}
Now, the problem part is in here:
public bool SaveOrderChanges(OrderProcess[] Order, int OrderID, int uid)
{
//2nd Step:
var ComparableObject = dbs.OrderProcessDB.Where(x => x.OrderID == OrderID).ToList();
var Objections = dbs.OrderDB.Where(x => x.OrderID == OrderID).FirstOrDefault();
dbs.DB.UpdateGraph(dbs.OrderDB, m => m.OwnedCollection());
dbs.SaveChanges();
return true;
}
I'd like to tell the differences between the Order parameter and the one I extract from OrderProcessDB. These are a One to Many Relationship.
I do not know how to use GraphDiff for this scenario. Any ideas?
You could just expose the base DbContext object in the interface, but that would violate basic principles of encapsulation. The challenge is that the UpdateGraph method is a static extension off of the concrete DbContext class. Here is my solution:
First the interface:
public interface IMyDbContext
{
...
TEntity UpdateGraph<TEntity>(TEntity entity, Expression<Func<IUpdateConfiguration<TEntity>, object>> mapping = null) where TEntity : class, new();
}
Then the actual DbContext:
public class MyDbContext : DbContext, IMyDbContext
{
...
public TEntity UpdateGraph<TEntity>(TEntity entity, Expression<Func<IUpdateConfiguration<TEntity>, object>> mapping = null) where TEntity : class, new()
{
return ((DbContext)this).UpdateGraph(entity, mapping);
}
}
And lastly example usage inside of a repository:
public class MyRepository : IMyRepository
{
private readonly IMyDbContext _myDbContext;
public MyRepository (IMyDbContext myDbContext)
{
_myDbContext = myDbContext;
}
public async Task<SomeEntity> UpdateSomeEntity(SomeEntity updatedSomeEntity)
{
_myDbContext.UpdateGraph(updatedSomeEntity, map => map.OwnedCollection(p => p.SomeChildCollection));
await _myDbContext.SaveChangesAsync();
return updatedSomeEntity;
}
}
I realize this is old, but I just found out about GraphDiff and can hopefully help anyone else looking.
This is how you use GraphDiff:
db.UpdateGraph(orderToUpdate, map => map
.AssociatedCollection(t => t.Products)
.OwnedCollection(t => t.PaymentMethods));
This says to update the Order object, and that the Order owns the PaymentMethods (meaning it can actually remove those entities), and is associated with the Products entities (meaning it will remove them from the reference table).
public async Task<TEntity> GetByIdAsync(int id) {
return await Context.FindByAsync(id);
}
and
public IQueryable<TEntity> GetById(Expression<Func<TEntity, int>> predicate) {
return Context.Where(predicate).FirstOrDefault;
}
I'm new to repositories and looking for tutorials and now kinda know what it does but the Task struck me. Between the two which is more preferred? I know it's a stupid question but it would help me understand them better. Any help would be much appreciated. Thanks!
First to your question:
GetByIdAsync: is used to load the data asynchrone from the database, If you have a lot of data for example you have to load about 10000 entries from database then this method it will be the right choice(You can also use bulk operation).
GetById: synchrone load the data from the DB this method is good if your query take just a few milliseconds and does not be called a lot of times from the same thread.
How to use them:
var employee= await new EmployeeRepository.GetByIdAsync(1);---> your method(caller) must be here also Async otherwise, you have to use task.
var employee= new EmployeeRepository.GetById(1);
If your Repository class return IQueryable then you have to do ToList.First();
You need Entity framework 6 or later =>> support of Async.,
otherwise you have to do it by your self!
Example: Let say your business object:
public class Employee
{
public int Id { get; set; }
public string FullName { get; set; }
}
// Now using this we will have a simple context class.
public class HRContext : DbContext
{
public DbSet<DomainClasses.Employee> Employees { get; set; }
}
// After that, define the repository interface IEmployeeRepository.
public interface IEmployeeRepository : IDisposable
{
IQueryable<Employee> All { get; }
IQueryable<Employee> AllAsync { get; }
IQueryable<Employee> AllIncluding(params Expression<Func<Employee, object>>[] includeProperties);
Employee Find(int id);
Employee FindAsync(int id);
void InsertOrUpdate(Employee employee);
void Delete(int id);
void Save();
}
// Then the Repository class called EmployeeRepository.
public class EmployeeRepository : IEmployeeRepository
{
HRContext context = new HRContext();
public IQueryable<Employee> All
{
get { return context.Employees; }
}
public IQueryable<Employee> AllIncluding(params Expression<Func<Employee, object>>[] includeProperties)
{
IQueryable<Employee> query = context.Employees;
foreach (var includeProperty in includeProperties)
{
query = query.Include(includeProperty);
}
return query;
}
public Employee Find(int id)
{
return context.Employees.Find(id);
}
public void InsertOrUpdate(Employee employee)
{
if (employee.Id == default(int)) {
// New entity
context.Employees.Add(employee);
} else {
// Existing entity
context.Entry(employee).State = EntityState.Modified;
}
}
public void Delete(int id)
{
var employee = context.Employees.Find(id);
context.Employees.Remove(employee);
}
public void Save()
{
context.SaveChanges();
}
public void Dispose()
{
context.Dispose();
}
}
I get the soruce code from :
http://blogs.msdn.com/b/wriju/archive/2013/08/23/using-repository-pattern-in-entity-framework.aspx
For example for a generic repository:
public interface IGenericRepository<T> where T : class {
IQueryable<T> GetAll();
IQueryable<T> GetAllAsync();
IQueryable<T> FindBy(Expression<Func<T, bool>> predicate);
IQueryable<T> FindByAsync(Expression<Func<T, bool>> predicate);
void Add(T entity);
void Delete(T entity);
void Edit(T entity);
void Save();
}
Where T is the base entity for all your entities.
here is the complete generic example:
http://www.tugberkugurlu.com/archive/generic-repository-pattern-entity-framework-asp-net-mvc-and-unit-testing-triangle
For better separation of concern you can also combine the repository pattern with unit of work as described by Martin Fowler book:
http://martinfowler.com/eaaCatalog/unitOfWork.html
Those two pieces of code do different things.
First piece finds a single entity.
var user = await new Repo<User>.GetByIdAsync(12);
Second piece executes the where clause and returns the first element or null. It is badly named because it does not actually force searching by Id.
var user = new Repo<User>.GetById(u => u.Username=="Bob");
The task is there to support .NET 4.5 await and async commands.
I want to create a common database abstraction in order to expose the same interface without worrying about the type of the DbContext that the database manage.
Here there is an example in order to explain well the concept:
public interface IDatabase<T> where T : DbContext {
void Add<T>(T entity);
void Remove<T>(T entity);
void SaveChanges();
}
The implementation can be:
public MyDatabase<T> : IDatabase<T> where T : MyContext {
public T Context { get; private set; }
//singleton contructor ...
public void Add<TC>(TC entity) {
Context.Set<TC>().Add(entity);
}
public void Remove<TC>(TC entity) {
Context.Set<TC>().Add(entity);
}
public void SaveChanges {
Context.SaveChanges();
}
}
The goals of this design are different: expose the same interface in order to decouple logic from database, change quickly the database (context), create one time the context and reuse during all the application lifetime (lock mechanism are required).
The problem is that the interface hides all the types of the sets in the context.
Context.Set<TC>().Add(entity); //this line don't compile
I'm not sure that this design is the best practise. How can I implement a design that offers these features?
Why you does not use the standard pattern for example Repository pattern you can also combine it with UnitOfWork.
You make it complicated for your self, just check this.
public interface IMyClassRepository : IDisposable
{
IQueryable<MyClass> All { get; }
IQueryable<MyClass> AllIncluding(params Expression<Func<MyClass, object>>[] includeProperties);
MyClass Find(int id);
void InsertOrUpdate(MyClass myClass);
void Delete(int id);
void Save();
}
public class MyClassRepository : IMyClassRepository
{
DBContext context = new DBContext();
public IQueryable<MyClass> All
{
get { return context.Employees; }
}
public IQueryable<MyClass> AllIncluding(params Expression<Func<MyClass, object>>[] includeProperties)
{
IQueryable<MyClass> query = context.MyClasses;
foreach (var includeProperty in includeProperties)
{
query = query.Include(includeProperty);
}
return query;
}
public MyClass Find(int id)
{
return context.MyClasses.Find(id);
}
public void InsertOrUpdate(MyClass myClass)
{
if (myClass.Id == default(int))
{
// New entity
context.MyClasses.Add(myClass);
}
else
{
// Existing entity
context.Entry(myClass).State = EntityState.Modified;
}
}
public void Delete(int id)
{
var employee = context.Employees.Find(id);
context.Employees.Remove(employee);
}
public void Save()
{
context.SaveChanges();
}
public void Dispose()
{
context.Dispose();
}
}
public class MyClass
{
}