Entity framework code first - ef-code-first

I'm using EntityFramework.Patterns in my application and I need to implement soft deletion. Is it possible to implement it using ArchivableRepository ?
If yes can you describe how ?

I did a soft delete by adding an interface to the entity's that support soft deletion.
public interface ISoftDelete
{
DateTime? DeletedDate {get;set;}
}
public class Foo : ISoftDelete
{
public int Id { get;set; }
public DateTime? DeletedDate { get;set; }
}
Then in your Repository, add something like this
public void SoftDelete<T>(T entity) where T : class, IEntity
{
entity.DeletedDate = DateTime.UtcNow;
}
Usage is like this
var entity = repo.GetOne();
repo.SoftDelete(entity);
repo.SaveChanges();

Related

How to specify default property values for owned entity types in Entity Framework Core 2.0?

I have a simple POCO type, say something like
public class OwnedEntity {
public string stringProperty { get; set; }
public decimal decimalProperty { get; set; }
public bool boolProperty { get; set; }
public int intProperty { get; set; }
}
and an actual entity with an OwnedEntity reference
public class SomeEntity {
public string Id { get; set; }
public OwnedEntity OwnedEntity { get; set; }
}
I set up the relationship like described in the documentation using EF Core's Fluent API:
protected override void OnModelCreating (ModelBuilder builder) {
base.OnModelCreating (builder);
builder.Entity<SomeEntity> ().OwnsOne (e => e.OwnedEntity);
}
I can't find anything on how to define default-values for all the properties of OwnedEntity. I tried to initialize the properties like this:
public class OwnedEntity {
public string stringProperty { get; set; } = "initial"
public decimal decimalProperty { get; set; } = -1M;
public bool boolProperty { get; set; } = false;
public int intProperty { get; set; } = -1;
}
but with no effect. Same goes with the [DefaultValueAttribute] (but that was to expect since it's explicitly mentioned).
There's a bit of information on how to handle initial values for regular entities:
modelBuilder.Entity<SomeOtherEntity>()
.Property(e => e.SomeIntProperty)
.HasDefaultValue(3);
But since I'm facing an Owned Entity Type, I can't access the type via Entity<T>.
Is there a way of doing what I'm looking for?
Some things worth mentioning:
I have a solid amount of specific entities where most of them are using the OwnsOne relation
Declaring all OwnedEntity-properties in a base class is not an option since not all the entities have those properties
I`m using EF Core 2.0.3 and ASP.NET Core MVC 2.0.4
Edit:
Originally, I wanted to have newly created SomeEntity instances to come with preset properties for all of the 'embedded' SomeEntity.OwnedEntity properties.
But looking at how my associated controller works, it all makes sense... I have the following methods for the 'Create' operation:
[HttpGet]
public IActionResult Create () {
return View (nameof (Create));
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create (SomeEntity model) {
context.Add (model);
await context.SaveChangesAsync ();
// redirect etc.
}
Which means that no object is created for the [HttGet] overload of Create and all the HTML inputs linked to properties (via asp-for) are initially empty. Okay. So I guess the proper way of doing this is to manually create a new instance of SomeEntity and pass it to the Create view like this:
[HttpGet]
public IActionResult Create () {
return View (nameof (Create), new SomeEntity());
}
Is this the right approach then or are there some more things to keep in mind?
Assuming you understand what EF Core Default Values are for, and just looking for equivalent of Entity<T>().Property(...) equivalent.
The owned entities are always configured for each owner type by using the ReferenceOwnershipBuilder<TEntity,TRelatedEntity> class methods. To access this class you either use the result of OwnsOne method, or use the OwnsOne overload taking second argument of type Action<ReferenceOwnershipBuilder<TEntity,TRelatedEntity>>.
For instance, using the second approach:
builder.Entity<SomeEntity>().OwnsOne(e => e.OwnedEntity, ob =>
{
ob.Property(e => e.stringProperty)
.HasDefaultValue("initial");
ob.Property(e => e.decimalProperty)
.HasDefaultValue(-1M);
// etc.
});

ASP.NET MVC - Dependency Injection

I am going over dependency injection. I have an ASP.NET MVC project where the model is named Customers:
public class Customers
{
public ID get; set;
private Customer customer
public Customers()
{
customer = new Customer();
}
}
Now I am suppose to add classes in order to eliminate the dependency in the above class. For example, Customer is a dependency of the Customers class.
Customers should depend on an abstraction. I created an interface (or abstract class) named IStorageCustomer
public interface IStorageCustomer
{
}
Now I changed the Customers class to the following below:
public class Customers
{
public ID get; set;
private IStorageCustomer customer;
public Customers(IStorageCustomer customer)
{
this.customer = customer;
}
}
I need to know if the dependency has been eliminated in the above class. What else do I need to do? Please help. Any help will be greatly appreciated. Thank you.
You can install Ninject MVC. (be aware there are different version for each version of MVC)
This is a Nuget which manages the dependency Injection for you.
To make Ninject inject the right class, you should set it up in the NinjectWebCommon file.
private static void RegisterServices(IKernel kernel)
{
//all your bindings will be configured here
kerenl.Bind<IStorageCustomer>().To<Costumer>(); //if you want Customer instances to be injected everywhere you expect an IStorageCustomer
}
Also leave a default constructor for the class you want to inject instances into.
Instead of Customer, I will rename it to Person. Now here are the changes that I have so far. This is also including classes that I have just added. The only problem is that person in the Customers model class is inaccessible because it is private and also its type.
public class Customers
{
public int ID { get; set; }
private IStoragePerson person;
public Customers()
{
this.person = LocateCustomer.GetCustomer();
}
}
public class Person : IStoragePerson
{
public string person{ get; set; }
}
Don't know what to add for IStoragePerson
public interface IStoragePerson
{
}
public class LocateCustomer
{
public static IStoragePerson person{ get; set; }
public static IStoragePerson GetCustomer()
{
if(person == null)
{
person = new Person();
}
return person;
}
}

Updating From Database Causes Redoing The Inheritance

Using EF 5. Below is Model.cs file under the Model.tt
I was suggested to have an interface to be inherited by all the entities on the model for some reason. You see the two of them (Adress, Kids) below.
public interface IHasAutoID
{
int getAutoId();
}
public partial class Adress : IHasAutoID
{
public int ID { get; set; }
public Nullable<System.DateTime> date{ get; set; }
..
..
}
public partial class Kids : IHasAutoID
{
public int ID { get; set; }
public Nullable<System.DateTime> date { get; set; }
..
}
Whenever I "Update Model From Database", as the "Tables" are not selectable(I don't know why), I need to delete the whole model and create new connection to the database. No problem at all. But this causes interface inheritance goes missing. every time I need to inherit all entities(almost 50) from "IHasAutoID" interface. I need your expertise.
You can create separate partial classes that contain your customizations. This is how I would do it (assuming that each class has public int ID):
public interface IHasAutoID
{
int ID { get; set; }
int GetAutoId();
}
public partial class Address : IHasAutoID
{
public int GetAutoId()
{
return this.ID;
}
}
Note that this is a class beside the Address class generated by EF. By using an interface you have to implement the GetAutoId() in each partial class. An alternative could be to do this in an abstract base class. Personally, I prefer interfaces despite the larger amount of boilerplate code. Inheritance often complicates code more than necessary.
A third alternative is to modify the t4 template to include the interface and its implementation in the generated code. It's not too hard. (But it usually takes some trial and error).
One last comment: you apparently want get generated ID values. But these values are returned into new entities after EF executes SaveChanges, maybe you don't even need this interface?
Modify Model.tt
public string EntityClassOpening(EntityType entity)
{
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1}partial class {2}{3} : IHasAutoID",
Accessibility.ForType(entity),
_code.SpaceAfter(_code.AbstractOption(entity)),
_code.Escape(entity),
_code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType)));
}
add namespace of IHasAutoID
public string UsingDirectives(bool inHeader, bool includeCollections = true)
{
return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion())
? string.Format(
CultureInfo.InvariantCulture,
"{0}using System;{1}" +
"{2}using YourNamespace of IHasAutoID;",
inHeader ? Environment.NewLine : "",
includeCollections ? (Environment.NewLine + "using System.Collections.Generic;") : "",
inHeader ? "" : Environment.NewLine)
: "";
}

ASP.NET MVC4: IQueryable does not contain a definition for 'Add'

I have tried to make an MVC news system. I started by the use a pluralsight tutorial which was used to create a department with employees. I changed the idea to fit my own purposes, changing the departments to "category" and employees to "newspost". This all works out fine, but now I want to remove the categories, since I don't need categories for my news system. But I can't add to the database using entityframework when I do this.
I have an interface for the datasource that looks like this:
INewMvcSiteDataSource
public interface INewMvcSiteDataSource
{
IQueryable<NewsPost> NewsPosts { get; }
void Save();
}
This is inherited by my DB Context class:
NewMvcSiteDb
public class NewsMvcSiteDb : DbContext, INewMvcSiteDataSource
{
public NewsMvcSiteDb() : base("DefaultConnection")
{
}
public DbSet<NewsPost> NewsPosts { get; set; }
IQueryable<NewsPost> INewMvcSiteDataSource.NewsPosts
{
get { return NewsPosts; }
}
public void Save()
{
SaveChanges();
}
}
I then want to use it in the controller to add a newspost to the database:
NewsController
var newsPost = new NewsPost()
{
Subject = newsModel.Subject,
Content = newsModel.Content,
ImagePath = newsModel.ImagePath
};
_db.NewsPosts.Add(newsPost);
_db.Save();
But this is where the ADD fails with the message: 'System.Linq.IQueryable' does not contain a definition for 'Add' and no extension method 'Add' accepting a first argument of type 'System.Linq.IQueryable' could be found (are you missing a using directive or an assembly reference?)
Now as the error says, its caused by using IQueryable, but I have no idea how else to do it.
Can you guys help?
Thanks.
If you don't mind exposing DbSet via your interface (some people don't like the ORM bleeding into the application),you should be able to do the following:
public interface INewMvcSiteDataSource
{
DbSet<NewsPost> NewsPosts { get; }
void Save();
}
public class NewsMvcSiteDb : DbContext, INewMvcSiteDataSource
{
public NewsMvcSiteDb() : base("DefaultConnection")
{
}
public DbSet<NewsPost> NewsPosts { get; set; }
public void Save()
{
SaveChanges();
}
}

Code First Generic Repository with existing Database tables

I have a Generic Repository class using code first to perform data operations.
public class GenericRepository<T> where T : class
{
public DbContext _context = new DbContext("name=con");
private DbSet<T> _dbset;
public DbSet<T> Dbset
{
set { _dbset = value; }
get
{
_dbset = _context.Set<T>();
return _dbset;
}
}
public IQueryable<T> GetAll()
{
return Dbset;
}
}
I have an entity class Teacher, which maps to an existing table "Teacher" in my database, with exactly the same fields.
public class Teacher
{
public Teacher()
{
//
// TODO: Add constructor logic here
//
}
public int TeacherID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
I have the following code below which binds data from Teacher to a repeater control.
GenericRepository<Teacher> studentrepository = new GenericRepository<Teacher>();
rptSchoolData.DataSource = studentrepository.GetAll().ToList();
rptSchoolData.DataBind();
But I get an exception exception "The entity type Teacher is not part of the model in the current context". Do I have to do any additional work when using an existing database for code first?
You must create a context class that derives from DbContext. The class should have properties of type DbSet<T> which will give EF enough information to create and communicate with a database with default naming and association conventions. It will use properties like Student.Teacher (if any) to infer foreign key associations:
public class MyContext: DbContext
{
public DbSet<Teacher> Teachers { get; set; }
public DbSet<Student> Students { get; set; }
...
}
If the defaults are not what you want, or when you've got an existing database that you want to match with the names and associations in your model you can do two (or three) things:
Override OnModelCreating to configure the mappings manually. Like when the tables in the database have those ugly prefixes (to remind people that they see a table when they see a table):
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Teacher>()
.Map(e => e.ToTable("tblTeacher"));
...
}
(Less favorable) Use data annotations to do the same.
Turn it around and use Entity Framework Powertools to reverse-engineer a database into a class model including fluent mappings and a DbContext-derived context. Maybe easier to modify an existing model than to start from scratch.

Resources