I'm trying to make EntityFramework work with ASP .NET MVC3 using this tutorial:
http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/creating-an-entity-framework-data-model-for-an-asp-net-mvc-application
Ok, I have my database, my .edmx model, model classes but one first thing I don't get is:
How does my DbContext derived class even know my .emdx model ? I don't fine where the "link" is created in this tutorial (maybe having several thing with the same name "SchoolContext", for the context as for the connexionstring is confusing ...)
When I run what I got for now with the code:
MMContext context = new MMContext();
List<EntityUser> testList = (from u in context.Users
select u).ToList();
I get:
System.Data.Edm.EdmEntityType: : EntityType 'EntityUser' has no key defined. Define the key for this EntityType.
System.Data.Edm.EdmEntitySet: EntityType: EntitySet �Users� is based on type �EntityUser� that has no keys defined.
Thank you for your help.
Assuming you are using the Code-First approach, you have to define a Key in your Users class:
public class User
{
public int Id { get; set; }
// ...
}
As mentioned from Kyle, if your ID field is not named "Id" you have to add the [Key] attribute:
using System.ComponentModel.DataAnnotations;
public class User
{
[Key]
public int u_Id { get; set; }
// ...
}
Related
I recently started to learn about Azure Mobile Services, I followed this tutorial about it and the classes for my model are required to inherit from the EntityData class.
From the EntityData source code, an Id property is already defined to act as a primary key, but it is defined as string which doesn't work for my Model that uses int.
My class looks like this:
public partial class Role : EntityData
{
public Role()
{
this.Users = new HashSet<User>();
}
[Key]
public int RoleId { get; set; }
public string Title { get; set; }
public virtual ICollection<User> Users { get; set; }
}
If I try to use this class, I get an error message saying an Id property is already defined.
Is there a way to define a different property as a primary key? In case this change is not possible, is there a way to use this string Id property as an incremental primary key?
The best solution is to use automapper. Here's a blog post that outlines how to do it, essentially you store an int, but transform it into a string when it is sent over the wire:
http://blogs.msdn.com/b/azuremobile/archive/2014/05/22/tables-with-integer-keys-and-the-net-backend.aspx
I'm using the SimpleMembership.MVC3 package with my MVC3 application and I want to be able to access users from the table through Entity Framework
In examples for doing this with MVC4, you can simply create a POCO to mirror the User table that's been generated, add your DbSet in your DbContext implementation and then query the DbSet like you normally would, ie: context.Users.
This collection is always returning 0 items for me even though there are rows in the table. What am I doing wrong? Here's what I got so far:
[Table("User")]
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class TestContext : DbContext
{
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
}
}
In my service:
model.Accounts = context.Users.ToList();
Thanks!
You do not create your a POCO that mirrors the User table in order to access it directly from EF. There is already a POCO created by the Internet template when you created the project, which you can customize as described here. This same article also shows how you can access the user information by accessing EF directly. You do not create your own context, there is one already in place that you use. Here is a code snippet from that article.
var context = new UsersContext();
var username = User.Identity.Name;
var user = context.UserProfiles.SingleOrDefault(u => u.UserName == username);
var email = user.Email;
The article also has links to download the source code that demonstrates the details on how to do this.
I circumvented the membership classes entirely and implemented a pure EF membership system. I leveraged the System.Web.Helpers Crypto helpers to handle password hashing and just create the AuthCookie when needed.
I am using EF5 and .NET 4.5 targeting an Oracle 11g database through Oracle.ManagedDataAccess.Client. I set up a small table to test and the how it works.
Now here is a weird fact which shows no result on searching the web nor this site. On every query I have a last column like "Extent1"."Text_TextID"!!! This obviously makes Oracle to throw an error Invalid identifier as I have no column with such name nor another object in the database.
This happens no matter how many tables/columns I have and no matter how I name them (if I have several tables all will have this extra column in the query).
Anybody has any idea why this happens??
Sample code below:
//POCO class and mapping
[Table("LO_USERS")]
public class User
{
[Key]
[Column("USER_ID")]
public int UserID { get; set; }
}
//define the context
public class TestContext : DbContext
{
public TestContext():base("OracleConn")
{
}
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//replace the annoying dbo schema name. Note: even if I remove this, I still get the extra column in the query
modelBuilder.Entity<User>().ToTable("LO_USERS", "TEST_SCHEMA");
}
//create a new user
using (var db = new TestContext())
{
var user = new User();
db.Users.Add(user);
//here I set a breakpoint
db.SaveChanges();
}
The query as showing by VS2012 at the breakpoint:
SELECT
1 AS "C1",
CAST( "Extent1"."USER_ID" AS number(10,0)) AS "C2",
"Extent1"."Text_TextID" AS "Text_TextID"
FROM "TEST_SCHEMA"."LO_USERS" "Extent1"
Edit:
It is the same with EF6 and DotConnect.
I found it: the problem was I was referencing User class in another class as child object, like
public class Text
{
public virtual ICollection<User> Users { get; set; }
without specifying any foreign key column in user class and EF was trying to set one by its own.
Once I removed the line above the extra column disappeared from the select statement.
I used LINQ to SQL to generate a dbml file which contains the database model for my database table. I want to use UIHint to let MVC present some fields as DropDownLists or Checkboxes in edit mode. But if I change the file, it will be lost if it's been regenerated. How should I solve that issue? I'm quite new to MVC and still learning. I've set up a controller with views for all CRUD elements, but now I'm finetuning and I'm running into this problem.
Since Linq-to-SQL auto-generates partial classes, you'll need to create a partial 'buddy class' where you will add your Data Annotations. Your buddy class mirrors portions of the auto-generated class that you need to modify. You tie them together with [MetadataType(typeof(BuddyClassName))] The partial buddy class and the auto-generated partial class will be merged together when you compile your project.
In an example given that:
Your namespace is "Project.Models"
Your Linq-To-Sql class is called "Products"
using System.ComponentModel.DataAnnotations;
namespace Project.Models
{
[MetadataType(typeof(ProductsMeta))]
public partial class Products
{
// You can extend the products class here if desired.
public class ProductsMeta
{
// This is a Linq-to-Sql Buddy Class
// In here you can add DataAnnotations to the auto-generated partial class
[Key]
public int ProductKey { get; set; }
[Display (Name = "Product Name")]
[Required(ErrorMessage = "Product Name Required")]
[StringLength(255, ErrorMessage = "Must be under 255 characters")]
public string ProductName { get; set; }
[UIHint("MultilineText")]
public string Description { get; set; }
}
}
}
These articles were very helpful:
ScottGu: ASP.NET MVC 2: Model Validation
How to: Validate Model Data Using DataAnnotations Attributes
Validating with Data Annotation Validators
If you are going to use the entities directly you should create a partial class and add your annotations there. This way when the model is regenerated you will not lose your annotations.
In an effort to further abstract my repository layer I have attempted to follow the code-first approach as described here: http://msdn.microsoft.com/en-us/magazine/ee236639.aspx.
I have a many-to-many relationship between Account and Subscription entities. A Navigation property exists on each entity pointing to the other (e.g. Account.Subscriptions).
Before I created my own model I was using the Entity generated model and the below worked fine ("db" is the entity context) :
public IQueryable<Account> GetBySubscriptionId(int subId)
{
return from a in db.Accounts
where a.Subscriptions.Any(s => s.SubscriptionId == subId)
select a;
}
Now the model for Account looks like this:
public class Account
{
public int AccountId { get; set; }
public string Name { get; set; }
// nav properties
public virtual List<Subscription> Subscriptions { get; set; }
}
And when I try to run the same LINQ query now I get this error:
"The specified type member
'Subscriptions' is not supported in
LINQ to Entities. Only initializers,
entity members, and entity navigation
properties are supported."
Any suggestions greatly appreciated.
Try changing the signature from
// nav properties
public virtual List<Subscription> Subscriptions { get; set; }
to
// nav properties
public virtual ICollection<Subscription> Subscriptions { get; set; }
Shamelessly nicked from Scott Hanselmann's demo here - http://www.hanselman.com/blog/SimpleCodeFirstWithEntityFramework4MagicUnicornFeatureCTP4.aspx which uses this pattern, also here's a Scott Guthrie demo using the same idea http://weblogs.asp.net/scottgu/archive/2010/07/23/entity-framework-4-code-first-custom-database-schema-mapping.aspx .
List<T> is a concrete implementation of various interfaces (ICollection, IQueryable, IEnumerable etc), Entity Framework uses proxy objects when it retrieves things from the database, hence the virtual declarations, which use different implementations of these interfaces which is where your error is coming from.