ASP.MVC db Find(), but with non-primary key parameter - asp.net-mvc

How does one get a list of results by using a key that is not the primary key? To be more specific, I have a composite primary key where I would like to retrieve all the matches with one column's parameter.
I would think, in an ActionResult in the Controller, it's something like
tableModel tbmodel = db.tableModels.Find(i => i.partialPK == parameter)
but that's not the case, since Find() only works with the entire PK.
I declared my PKs in the entity model class as:
[Key]
[Column(Order = 0)]
public int PK1 { get; set; }
[Key]
[Column(Order = 1)]
public string PK2 { get; set; }

According to DbSet.Find you can pass in the primary keys separated by commas
db.tableModels.Find(PK1, PK2)
The Find method takes an array of objects as an argument. When working with composite primary keys, pass the key values separated by commas and in the same order that they are defined in the model.
However, if you want to just use one value, you will probably have to use
db.tableModels.Where(i => i.partialPK == parameter)
or an equivalent Linq operator

If you're trying to get the object with linq query from database, use: .FirstOrDefault with .Where
Customer customer = db.Customers.Where(c => c.Email == auth.Email).FirstOrDefault();
Here db is DbContext
and Customer is the DbSet

Related

How to map table without primary key Entity Framework

I'm using Entity Framework to map some tables, but I can't do this unless I declare some column as the primary key.
The problem here is that my table in my database don't have a primary key and has millions of rows. I don't have permission to create a new Id column.
[Table("MYTABLE")]
public class myTable
{
[Column("NUMX")]
public virtual string NumX { get; set; }
[Column("NAME")]
public virtual string Name { get; set; }
[Column("AGE")]
public virtual int AGE { get; set; }
}
Obs: If I add the [Key] attribute to some column like Age, it works, but returns the wrong data.
Is there some way to omit the primary key?
I Figured out the problem.
Composite Keys works for me:
eg:
In my Context I defined some keys, not only one, but three keys:
public class MyContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
**//Here is the secret**
modelBuilder.Entity<MyModel>().HasKey(x => new { x.NumX, x.Name,x.Age});
}
}
Entity Framework requires a primary key unlike SQL.
EF use the primary key to uniquely identify rows (for example when you use .Find() or to perform update operations).
Infact not having a primary key remember a SQL VIEW, where you can only read data.
If any of the columns uniquely identify a certain row set it as a primary key (it can't be NULL) also if in Sql it isn't a key.
Otherwise if the combination of the columns are uniquely, create a composite key with these columns.
Remember that you should have a primary key in the 99% of cases, when you don't have a primary key you should stop and think if it make sense.

How to include only a single property when using 'expand'

I have an orders table which I want to query. One of the properties is "UserId" and which turns into a navigation property to the User.
I can query this to get the order and the associated User. However, I don't want the entire User entity, only the UserName property.
How do I construct that query in breeze?
Something like:
let query = new breeze.EntityQuery()
.from("orders")
.expand("user.userName");
I tried this, but then returned objects are not actually entities, but it does return just the userName:
let query = new breeze.EntityQuery()
.from("cases")
.select("field1, field2, user.userName");
Is there any other way of doing this? Note that I am using EF on the backside.
The best solution I found for this is creating a "virtual entity" which consists of just the two fields that I want. In other words, I have AspNetUsers as one table with it's corresponding entity. And then I have a second code first entity which consists of only the Id, and the UserName:
[Table("AspNetUsers")]
public partial class User
{
[Key]
[Column("Id")]
public string AspNetUserId { get; set; }
[StringLength(256)]
public string UserName { get; set; }
}
I can then use it as a relation in other tables and include it like was just another table.

Entity Framework Code First : One-To-One association using Annotations

I am having .NET MVC 5 and Identity...
I am trying to get a one to one relationship for my Member class to my MemberInfo class..
So, My classes looks something like this:
IdentityUser is in the Microsoft.AspNet.Identity.EntityFramework namespace with string Id as its ID.
public class GRNUser : IdentityUser {
....
....
}
public class MemberUser : GRNUser {
public virtual Member MemberInfo {get; set; }
}
public class Member {
public int ID {get; set; }
public string MemberUserID {get; set; }
public virtual MemberUser MemberUser { get; set; }
}
In my Context, I have this
modelBuilder.Entity<Member>().HasRequired(m => m.MemberUser)
.WithOptional(u => u.MemberInfo);
So, the MemberUser and Member should be able to navigate to and from each other using the MemberUser's ID property and Member's MemberUserID property.
However, when my Database is created, it has an additional column "MemberUser_Id" instead of using my MemberUserID that I specified. How do I make it use "MemberUserID" that I specified?
I've tried using a few combination so of the ForiegnKey Data Annotation, but keeps on getting this error:
Member_MemberUser_Source: : Multiplicity is not valid in Role 'Member_MemberUser_Source' in relationship 'Member_MemberUser'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.
I don't know whether i understood you right or not, but i'l do my best to help.
(I'l assume that you work with code first migration)
If you want to make a one-to-one relation, why not try to make a standalone entity for your info which will have a foreign key for the user entity and that foreign key will be annotated as the primary key of the entity?
Another way is why just not add whatever attributes you like to the Application User entity and work with it?
In any case i might have misunderstood your purpose, so please feel free to explain further since your post is a bit confusing.

EF Code First Modelbuilder creating unique identifiers where it should not

I have something like this:
modelBuilder.Entity<TransactionHistory>()
.HasOptional(history => history.Sender)
.WithMany()
.Map(s => s.MapKey("Sender"))
.WillCascadeOnDelete(false);
modelBuilder.Entity<TransactionHistory>()
.HasOptional(history => history.Receiver)
.WithMany()
.Map(s => s.MapKey("Receiver"))
.WillCascadeOnDelete(false);
And in my table TransactionHistory, it creates unique identifiers at columns Sender and Receiver. I don't want those columns to be unique, what do i do?
TransactionHistory model:
public class TransactionHistory
{
public Account Sender { get; set; }
public Account Receiver { get; set; }
}
Edit: Ok. Apparently uniqueidentifiers are not the case. The problem is, that when i am adding transactionhistory item into database, i got the following error:
Violation of PRIMARY KEY constraint 'PK_dbo.Accounts'. Cannot insert
duplicate key in object 'dbo.Accounts'.\r\nThe statement has been
terminated.
An i add this item like that:
context.Transactions.Add(history);
context.savechanges();
(Transactions is a transactionhistory object)
EF uses uniqueidentifier as SQL column type for the foreign keys because the principal's (= Accounts) primary key is a uniqueidentifier - in C# it is a Guid, like public Guid AccountId { get; set; }.
It must choose this type because principal and dependent key types must match in a foreign key relationship in the database.
This does not mean that the foreign key column is unique (or has a unique index). Of course you can use the same uniqueidentifier value multiple times as the foreign key column value.
Entity framework works by storing a cache of a bunch of objects in DBContext. Even if all the properties are the same on your Account object (including your pk) entity framework will see this as a new object unless you remind it "hey, you already know about this". I can think of 2 ways to do this:
context.Entry(history.Sender).State = EntityState.Modified;
context.Entry(history.Receiver).State = EntityState.Modified;
or
Make sure when you set the Accounts on your history object that they are already attached to your dbcontext.
var sender = context.Accounts.FirstOfDefault(...your condition here...);
var receiver = context.Accounts.FirstOfDefault(...your condition here...);
history.Sender = sender;
history.Receiver = receiver;
Also EF does not load navigation/related entities unless you tell it to. So if you are editing history make sure you using .Include() to pull in your related objects.
Hope that helps.

EF code first - change generated column name for relationship

Using EF code first want to control the name of the genereted column WHEN REFERENCING SELF. Tried [ForeignKey] and [Column] attributes. [Column] does not work and [ForeignKey] forces a relationship that seems to cause a problem. I have used [ForeignKey] attribute to set the name of a column in another class/table connected to this one.
Have
public class Episodes
{
public long ID {get; set;}
// ... other properties
public List<Episodes> Children { get; set; }
}
want a table (ID, ..., ParentID) - get a table (ID, ..., Episode_ID)
If you don't have the foreign key column exposed as property in your entity class you can define the column name only with Fluent API:
modelBuilder.Entity<Episodes>()
.HasMany(e => e.Children)
.WithOptional()
.Map(m => m.MapKey("ParentID"));
I assume that the parent is optional (ParentID is a nullable column in the DB table) because, I guess, there should be some "root" in the tree, i.e. an episode that doesn't have a parent anymore, hence at least for this episode the ParentID column must be NULL.

Resources