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)
: "";
}
Related
Here is the problem I need to solve:
I need to display a grid that contains a group of columns that are dynamic, meaning that the number can change depending on the user parameters.
I have attached a sample below as an image to illustrate:
GRID SAME IMAGE
I have these c# POCOs to keep my question simple
public class OrderItem
{
public string ProductName { get; set; }
public string Status { get; set; }
public List<CityOrderInfo> CityOrders { get; set; }
}
public class CityOrderInfo
{
public int OrderCount { get; set; }
}
I have a web api controller that is able to accept the OData request, plus other arguments that the repository accepts. However the problem is that while the parameter $orderby for ProductName and Status works, when I do "$orderby='CityOrders[1]\OrderCount asc' it fails.
public class OrdersControllers : ApiController
{
private readonly IOrdersRepository _repository;
public OrdersControllers(IOrdersRepository repository)
{
this._repository = repository;
}
public IEnumerable<OrderItem> GetOrderItems([FromUri] ODataQueryOptions<OrderItem> oDataQuery)
{
var result = this._repository.GetOrders().ToList();
var queryableData = oDataQuery.ApplyTo(result.AsQueryable());
var transformedData = queryableData as IEnumerable<OrderItem>;
return transformedData;
}
}
The reason I opted to hold the city orders in list is because I thought it would too painful to make a POCO with every city in the USA as a property so instead made it more generic.
The question is how can a sort on a property that holds a list using OData? Is this possible? I keep getting syntax error at position n. As of now I have not found an answer.
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();
}
}
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.
I am sure i am just missing some pretty basic here, but i can't seem to figur it out.. maybe because its been a while since i have been on the .NET platform.
Anyway, I have this database structure i the ASP.NET MVC3 framework where i have "Coruse", "Tool" and "ToolADL"(Inheritance from Tool). A "Course" can have one-or-more "Tools" where one of the "Tool"-types is "ToolADL".
Models/Course.cs:
public class Course {
[Key]
public int CourseID { get; set; }
[Required(ErrorMessage = "{0} er påkrævet")]
[Display(Name = "Værktøj")]
public virtual ICollection<Tool> Tools { get; set; }
}
Models/Tool.cs:
public abstract class Tool {
public Tool(){
Priority = 0;
}
[Key]
public int ToolID { get; set; }
[Required]
public int CourseID { get; set; }
[Required]
public int Priority { get; set; }
}
Models/ToolADL.cs:
public class ToolADL : Tool {
[Required]
public string Image { get; set; }
}
aaand the Models/ProjectContext:
public class ProjectContext : DbContext {
// Course context
public DbSet<Course> Courses { get; set; }
// Tools
public DbSet<Tool> Tools { get; set; }
// ToolADL
public DbSet<ToolADL> ToolADLs { get; set; }
}
Now when i try to create the controller and connect to DbContext and the Model to it so the entity framwork can do its magic, I get the following error in the ToolADL controller Details function (and others) where time i use "find()":
ToolADLController.Details(int):
private ProjectContext db = new ProjectContext();
public ViewResult Details(int id){
ToolADL tooladl = db.Tools.Find(id);
return View(tooladl);
}
Error 1 Cannot implicitly convert type 'Project.Models.Tool'
to 'caREhab_community.Models.ToolADL'. An explicit conversion exists
(are you missing a cast?) C:\Users\Thor\Documents\Visual Studio
2010\Projects\Project\Project\Project\ToolADLController.cs 29 31 Project
(I changed the name of the orginal project to "Project")
I simply cannot figur out what I am doing wrong, Is it wrong types, some really basic about Inheritance i left out or something else?
Hope some kind soul can tell me why I am an idiot and can't figure this out :)
If object that is returned by db.Tools.Find(id) is of type ToolADL then you should do:
ToolADL tooladl = db.Tools.Find(id) as ToolADL;
After that You'll have your object or null.
If it's not of type ToolADL then you can't do this because:
When You have:
public class A { }
public class B : A { }
You can not do something like this:
A a = new A();
B b = a;
This is in fact a basic truth about inheritance.
You might change this implicit conversion to explicit on by doing:
B b = (B)a;
Then your code would compile but You would get a runtime exception:
Unable to cast object of type 'A' to type 'B'.
To make it work You would have to specify an explicit conversion like this:
public class A
{
public static explicit operator B(A a)
{
return new B();
}
}
But this will give you yet another compile time error:
'A.explicit operator B(A)': user-defined conversions to or from a
derived class are not allowed
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();