Repository Inserting c# - c#

Controller:
var d = new Repository<Department>(new MyDBEntities());
var newDepartment = new Department();
newDepartment.Name = "Software Department";
d.Insert(newDepartment); //I insert data here
Model:
public class Repository<T> where T : class
{
protected DbSet<T> DbSet;
public Repository(DbContext dataContext)
{
DbSet = dataContext.Set<T>();
}
public void Insert(T entity)
{
DbSet.Add(entity);
}
}
I need to insert data to my database.However if i insert data , it does not work , whenever i check my database, data never appears in my database, also i can not see anything like "SaveChanges();"in DbSet.
Where i miss exactly ?
Thanks

After Inserting data. I think you need to update your DBSet. go here to have some info :DbSet(TEntity)

In my understanding , you still need to call SaveChanges() from DbContext underlying your DbSet to actually save the data to database.
DbSet.Add() : Adds the given entity to the context underlying the set in the Added state such that it will be inserted into the database when SaveChanges is called. [MSDN]

Related

Remove an entity without fetching it in the generic repository pattern entity framework

I am trying to delete an entity of Employee from the database which contains different tables like Employee, Project, Skills using a generic repository pattern.
namespace Information.Repository
{
public class IRepositoy<TEntity> : IRepository<TEntity> where TEntity : class
{
private readonly ApplicationDbContext _dbContext;
public IRepositoy(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
public void Remove(int id)
{
TEntity element = _dbContext.Set<TEntity>().Find(id);
_dbContext.Set<TEntity>().Remove(element);
}
}
}
When the above Remove method is called it makes two database call
One for getting the entity.
Second for deleting it.
I have found the query like the below one which executes with single SQL query
when the entity type(Employee or Project or Skill) is known
public void Remove(int id)
{
Employee employee = new Employee { EmployeeId = id };
_dbContext.Entry(employee).State = EntityState.Deleted;
}
can anyone please suggest me how to delete an entity without fetching it using a generic repository pattern similar to the above example.
Using raw SQL
Entity Framework doesn't allow you to delete an object that you haven't loaded (or attached). This also extends to conditional deletes (e.g. deleting all users named John) as it requires you to load the users before deleting them.
You can get around this by executing raw SQL. It's not ideal as you tend to use EF so you don't have to write SQL, but the lack of a decent delete behavior (without loading) makes this an acceptable solution.
Something along the lines of:
using (var context = new FooContext())
{
var command = "DELETE * FROM dbo.Foos WHERE Id = 1";
context
.Database
.ExecuteSqlCommand(command);
}
Where relevant, don't forget about SQL injection protection. However, it's usually a non-issue for simple deletes as the FK is usually a GUID or int, which doesn't expose you to injection attacks.
Making it generic
The example you posted works as well, but you're probably not using it because it can't easily be made generic-friendly.
What I tend to do in all my EF projects is to have an (abstract) base class for all my entities, something along the lines of:
public class BaseEntity
{
public int Id { get; set; }
public DateTime CreatedOn { get; set; }
public string CreatedBy { get; set; }
public DateTime? UpdatedOn { get; set; }
public string UpdatedBy { get; set; }
}
An interface would also work, I just prefer a base class here.
The audit fields are not part of this answer but they do showcase the benefits of having a base class.
When all your entities inherit from the same base class, you can put a generic type constraint on your repositories which ensures that the generic type has an Id property:
public class IRepositoy<TEntity> : IRepository<TEntity> where TEntity : BaseEntity
At which point you can generically implement your proposed solution:
public void Remove(TEntity obj)
{
dbContext.Entry(obj).State = EntityState.Deleted;
}
You can also specify a parameterless constructor type constraint:
where TEntity : BaseEntity, new()
which enables you to instantiate your generic type as well:
public void Remove(int id)
{
TEntity obj = new TEntity() { Id = id };
dbContext.Entry(obj).State = EntityState.Deleted;
}
Note
There is a generic raw SQL solution as well, but I've omitted it as it is more complex because it requires you to retrieve the table name based on the entity type.
The raw SQL variant is only valuable in cases where you want to execute conditional deletes (e.g. removing all entities whose id is an even number).
However, since most conditional deletes are entity-specific, this means that you generally don't need to make them generic, which makes the raw SQL approach more viable as you only have to implement it in a specific repository and not the generic one.
You still have to fetch it. Entity Framework caches your dbSets so it's usually pretty quick. Use the same context like so:
public virtual void Delete(object id)
{
TEntity entityToDelete = dbSet.Find(id);
Delete(entityToDelete);
}
public virtual void Delete(TEntity entityToDelete)
{
if (context.Entry(entityToDelete).State == EntityState.Detached)
{
dbSet.Attach(entityToDelete);
}
dbSet.Remove(entityToDelete);
}
Where dbSet =
context.Set<TEntity>();
The current limitation of Entity Framework is, in order to update or delete an entity you have to first retrieve it into memory. However there are few alternatives to delete a specific record.
You can try ExecuteSqlCommandto delete a specific record
_dbContext.Database.ExecuteSqlCommand("Delete Employee where EmployeeId = {0}", id );
or try using EntityFramework.Extended Library to delete a specific record
_dbContext.Settings.Where(s=> s.EmployeeId == id).Delete();

Set Entity State to Modified for entities with different reference

I am working on WPF Application using MVVM pattern, also I use EF code first for database entities. and because of MVVM I use AutoMapper to map objects from Database "Models" to "ViewModels".
When I update an entity I have to map it back from view model to model and pass it to the update method
public void Update(TEntity entity)
{
TEntity databaseEntity = Context.Set<TEntity>().Find(entity.Id);
DbEntityEntry dbEntityEntry = Context.Entry(databaseEntity);
dbEntityEntry.CurrentValues.SetValues(entity);
dbEntityEntry.State = EntityState.Modified;
}
The problem here I have to Get the entity each time I want to update it, and if I have many objects to update it will cause performance issue. I tried to use this following code but it didn't work because the auto mapper create new instance of the entity different than the one attached with EF dbConext.
public void Update(TEntity entity)
{
DbEntityEntry<TEntity> dbEntityEntry = Context.Entry(entity);
dbEntityEntry.State = EntityState.Modified;
}
I tried to handle this by overriding Equals and GetHashCode methods but it also didn't work.
Is there any way to handle update entity without getting it form the database?
Thank you.
Since you're manually tracking changes you should not retain a reference to the same dbcontext. Read your data inside a Using statement which news up and disposes the dbcontext.
When you write the data back new up an entity, set the properties to those from your viewmodel, set it's state to modified and savechanges.
Again, open and close your dbcontext round this.
There is then no need to go find the entity you read.
Here's a trivial example in case that explanation was unclear.
This does not represent a best practice enterprise solution - I would expect at least a generic updateentityasync method.
We're updating a Person in a People table.
public async Task<bool> UpdatePersonAsync(Person person)
{
int numUpdated = 0;
using (var db = new AndyPeopleContext())
{
db.People.Add(person);
db.Entry(person).State = EntityState.Modified;
numUpdated = await db.SaveChangesAsync();
}
return numUpdated == 1;
}

C# Entity Framework DBContext

I am trying to learn Code First EF6 and I am confused regarding DBContext.
The database I will be working on contains 800+ tables, while when working of specific parts of the application I am only dealing with 1-10 tables.
So my question is; would not having a DBContext involving 800+ Classes have a big negative impact on system resources?
I guess I am new to this technology and confused regarding the actual meaning of the information that I am taking in during my research.
Thank you.
NOTE: Thank you for your inputs. Please take a look at this post: Using multiple DbContexts with a generic repository and unit of work. There it states I cannot have tables in separate contexts that relate to each other?!
But in a real world scenerio my understanding is that it is common to break up the table relationships in focused areas, how is this done in Code First EF? Thanks again.
Updated
If you are using Repository Pattern, you cannot go make multiple DbContext, You Create One Generic, And pass it to your Generic Repository like below :
public class Repository<T> : IRepository<T>
where T : EntityBase
{
internal MyDbContext context;
internal DbSet<T> dbSet;
public Repository()
{
context = new MyDbContext();
this.dbSet = context.Set<T>();
}
public void Add(T entity)
{
dbSet.Add(entity);
}
public void Delete(T entity)
{
dbSet.Remove(entity);
}
public void Delete(int id)
{
dbSet.Remove(dbSet.Find(id));
}
public T GetById(int id)
{
return dbSet.Find(id);
}
public IEnumerable<T> GetAll()
{
return dbSet.AsEnumerable();
}
public void Update(T entity)
{
dbSet.Attach(entity);
context.Entry(entity).State = EntityState.Modified;
}
public void Save()
{
context.SaveChanges();
}
}
And you should include your DbSets there as well.
If you are doing EF Code-First then its yours to design your POCO class based on how many are needed but no more. But based on what you said about 800 tables i think you may want to try Database-First Approach rather. i suggest you this article very carefully as it explain everything you need.
Update:
If you Approach this from DataBase-First: Ado.NET Entity Model Creates your DbContext for you! If you take a closer look at the .Edmx file it is basically your POCO Classes within.
Now if you try Code-First Approach, lets say you have this DbContext Class:
public class MyDbContext : DbContext
{
public MyDbContext()
: base("name=MyConnection")
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyDbContext, YourApplication.Migrations.Configuration>("MyConnection"));
}
//Every time you need to add new Table you add them here.
public DbSet<Users> Users { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//And Map them here
modelBuilder.Configurations.Add(new UsersMap());
}
}
You just add a new DbSet<Class> to your DbContext like below:
public DbSet<POCO CLASS> CLASS { get; set; }
And so on, i normally create a DbContext for Every Area i have in my MVC Application. So you can go like Admin Area -> AdminDbContext And so on.
You only need the tables you are working with in your db context (if the db already exists). The only reason you'd need a db context with all the tables would be if you want to recreate the whole db from scratch.
Take a look at the bounded context pattern from DDD: http://martinfowler.com/bliki/BoundedContext.html

Saving in entity framework

I have read this article and still misunderstanding key moments. Don't we need call
_context.SaveChanges()
in every Delete/Update/... operations?
If I change property of any entity does SaveChanges() submitted result to database or I must manually set EntityState.Modifyed?
Here is my code:
public class Repository<T> : IRepository<T>
where T : class
{
private IDbContext _context;
public Repository(IDbContext context)
{
_context = context;
}
private IDbSet<T> DbSet
{
get
{
return _context.Set<T>();
}
}
#region IRepository<T> Members
public void Insert(T entity)
{
DbSet.Add(entity);
}
public void Delete(T entity)
{
DbSet.Remove(entity);
}
public IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate)
{
return DbSet.Where(predicate);
}
public IQueryable<T> GetAll()
{
return DbSet;
}
public T GetById(int id)
{
return DbSet.Find(id);
}
#endregion
}
public interface IDbContext
{
IDbSet<T> Set<T>() where T : class;
int SaveChanges();
void Dispose();
}
You ask:
Don't we need call
_context.SaveChanges()
in every Delete/Update/... operations?
No we don't. When calling Delete we don't accually delete the entity - we mark it for deletion.
Same thing with Update, although you dont have to do anything other that make the changes you want to the entity. All properties (generated by the default template) will implement INotifyPropertyChanged so it knows when a entity is modified.
All entities (in database first - autogenerated by defullt template) have a State property. This property is maintained by the ObjectContext as long as the chages take place within the scope of the ObjectEntity.
e.g.
Customer c;
using(var context = new MyEntityContext())
{
c = context.Customer.FirstOrDefault(); //state is now Unchanged
c.Name = "new name"; // this set the State to Modified
//context.SaveChanges(); // will persist the data to the store, and set the State back to unchaged
}
//if we look at our customer outside the scope of our context
//it's State will be Detacth
Console.WriteLine(c.State);
Then you call SaveChanges all entites that have a state of Added Deleted or Modified will have their changes persisted to the database in a local transaction
EDIT
If an entity is marked for deletion, and you try to modify it - you will get an InvalidOperationException
You can perform many changes in your in-memory context,
such as inserts, updates and deletes.
Once you call SaveCahnges() all the changes you've made will be saved
in the DB at a single transaction.
This means that eiteher they are all submited, or none of them
in case of an error.

EF 4 can't seem to call SaveChanges

I have this Context with the following method override :
public class MyContext : DbContext
{
public DbSet<Contract> Contracts{get;set;}
public override int SaveChanges()
{
Contract ctr = new Contract
{
ContractId = "CT99999991",
ContractNumber = "9000",
LastModifiedDate = DateTime.Now,
GracePeriod = DateTime.Now,
ShipByDate = DateTime.Now,
ExpirationDate = DateTime.Now
};
this.Contracts.Add(ctr);
return base.SaveChanges();
}
}
No matter what I tried, I never succeed in making this part of the code succeed.
I would love to save the upper Contract in the database on SaveChanges event occurence.
Is there something I'm overlooking ?
This isn't something I've tried to do myself, but it's possible that because you're inside the SaveChanges() method already, the context's changelist has already been created. So when you add your new Contract to the context's Contracts collection, you would have to make your context rebuild its list of changes that need to be persisted back to the database before calling base.SaveChanges()
What you should instead do is to hook into the SavingChanges event of the ObjectContext. This will allow you to save to an archive/audit table. Here is an article that explains how to do it. I've done this before and it works really well.
I was hooking into the custom Context class ( class MyContext : DbContext ) and it wasn't working.
I finally resorted to hooking into the WCF Data Service class (class MyDataService : DataService ) and it works well.

Categories