Get the current logged in IdentityUser? - entity-framework

I'm trying to create an application where I'm using Windows Identity and Entity Framework Code First. So I'm creating a custom class to save some data.
public class Order {
public string Name { get; set; }
public DateTime CreatedDate { get; set; }
public IdentityUser User { get; set; }
}
Now I'm trying to link the user table to the order table (as generated by Entity Framework). So that I can do Order.User to get user info on the user who created the Order.
I want to create a new order using
new Order {
Name = "Test",
CreatedDate = new DateTime(2014, 3, 30),
User = <What goes here?>
}
Now how to I get "IdentityUser" of the currently logged in user? Or am I going about this the wrong way?

You can get the current user from User.Identity inside of a controller, and HttpContext.Current.User.Identity from outside. Check this: ASP.NET MVC 5 - Identity. How to get current ApplicationUser

Related

EntityFramework DatabaseGeneratedOption.Identity accepts and saves data instead of generating new one

Assuming this test model:
public class TestEntity
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
}
When I generate a new instance of it, Id is 00000000-0000-0000-0000-000000000000.
Saving such an instance in the database as a new row, results in a Guid being generated (which is different from the empty one).
However, if I provide a valid Guid in TestEntity.Id, the new row is created with the provided Guid instead of a newly computed one.
I would like this behavior to exists only when editing a row, not when creating it. This is to ensure a database-layer protection from attacks where a user normally shouldn't get to choose which data to input.
Off course this protection is present in other layers, but I want it in the database too. Is this possible? How can I tell EF to ignore model data when creating a new row?
DatabaseGeneratedOption.Computed descriptions says
the database generates a value when a row is inserted or updated
So clearely that's not an option. I don't want to change Id when updating a row. I only want to be sure no one can create a row and choose the Id.
I'd try to keep things simple. Make your set method protected, then you have two ways to generate Ids, You can generate it by yourself inside a constructor:
public class TestEntity
{
// no need to decorate with `DatabasGenerated`, since it won't be generated by database...
[Key]
public Guid Id { get; protected set; }
public string Name { get; set; }
public TestEntity()
{
this.Id = Guid.NewGuid();
}
}
...or you can let the database generate it for you. At least for SQL Server, it will be able to generate for int and Guid as well:
public class TestEntity
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public Guid Id { get; protected set; }
public string Name { get; set; }
// no need to generate a Guid by yourself....
}
This will avoid people from setting a value to Id outside the class (therefore no one can choose a Guid for new rows, or modify from existing ones).
Of course, your team could use reflection to by-pass class definitions, but if that's the case, you need to have a talk with your team.
If you still want to make sure they won't cheat, then you'd have to do check before saving changes to database, maybe overriding SaveChanges() in your DbContext.
As a side note, for both int and Guid, values are not generated by Entity Framework. Decorating the property with [DatabaseGenerated(DatabaseGeneratedOption.Identity)] will tell Entity Framework to generate a column with a default value coming from the own database provider.

Entity Framework 7 (Beta 7) and Entity Tracking

I am trying to separate my domain model (which is responsible for my business logic) with my data model which is what EF 7 uses to build my schema.
I am running into a problem with regards to persisting changes made to my domain model to my database
So for example given that I have the Data Model PersonTable and the Domain model Person:
public class PersonTable
{
public virtual Guid Id { get; set; }
public virtual String Name { get; set; }
public virtual String Surname { get; set; }
}
public class Person
{
public virtual Guid Id { get; set; }
public virtual String Name { get; set; }
public virtual String Surname { get; set; }
//Other Domain Methods and Constructors...
}
And I want to persist my domain changes to my database by doing this:
public void Update(Person p)
{
var person = new PersonTable
{
Id = p.Id,
Name = p.Name,
Surname = p.Surname
}
PersonDbContext.Update(person);
PersonDbContext.SaveChanges();
}
When I try to apply these changes I get an InvalidOperationException saying
"The instance of entity type 'Tables.PersonTable' cannot be tracked because another instance of this type with the same key is already being tracked. For new entities consider using an IIdentityGenerator to generate unique key values."
I assume this has something to do with entity tracking but how does this work in EF 7? I want to be able to apply this pattern so that I can seperate these two models.
// Before updating we have fetch original data row from database.
// So we need to use AsNoTracking().
var originalPerson = PersonDbContext.Person.AsNoTracking().FirstOrDefault(p => p.Id == id);
and at time of save we need to use following code.
PersonDbContext.Entry(originalPerson).Context.Update(newPersonDetail);
The error occurs when your instance of PersonDbContext is already tracking an instance of Person with the same Id.
To debug this, inspect what you have tracking already in PersonDbContext.ChangeTracker.Entries(). I expect you will discover you already have an entry for PersonTable.Id that matches the one you are attempting to update.
To ensure you don't get these conflicts, don't reuse PersonDbContext across threads or multiple HTTP requests (if this is a web app.)
I was facing the same error. I found the answer in this other thread here
https://stackoverflow.com/a/31840042/1716912. I changed my repository DI to be scoped from being a singleton.

AutoMapper - Trying to pass variables from WEB API Controller to Automapper configuration at runtime

I am working on a large project that uses AutoMapper to map entities to DTO's - this works perfectly for simple mappings but I've come unstuck at the moment trying to get some custom mappings to work.
This is a simplified example of what I am trying to do. I have a Product, Price and Store class:
public class Product
{
public Guid Id { get; set; }
public ICollection<Price> Prices { get; set; }
}
public class Price
{
public Guid Id { get; set; }
public Guid ProductId { get; set; }
public Guid StoreId { get; set; }
public decimal Value { get; set; }
public virtual Product Product { get; set; }
public virtual Store Store { get; set; }
}
Each class also has a DTO. When I access a ProductDTO class by default I will get all prices for all stores. However, when a particular store logs in to the application I want to limit the prices they see to their store only.
I would like AutoMapper to be able to handle this so that when my WEB API Controller calls into the Repository to get a ProductDTO, the list of Prices are automatically filtered to include ONLY the currently logged in stores' prices.
I have set up my AutoMapper configuration in the Startup class of my WEB API project. I know I could set up a custom mapping like so:
Mapper.Configuration.CreateMap<Product, ProductDto>()
.ForMember(pd => pd.Prices,
opt => opt.MapFrom(p => p.Prices.Where(pp => pp.StoreId == storeId));
but I only know what the currently logged in store ( the storeId ) is once the request comes into the WEB API Controller. So, is it possible to set up my configuration in a way that I can update the configuration during runtime or is there a better way of tackling this altogether ? This is a very simple example - there are hundreds of similar scenarios in this project I am working on ( not limited to filtering by Store ID ) so I would like to implement something as generic as possible.
You need to use parameterized LINQ query support in AutoMapper:
int storeId = 0;
Mapper.Configuration.CreateMap<Product, ProductDto>()
.ForMember(pd => pd.Prices,
opt => opt.MapFrom(p => p.Prices.Where(pp => pp.StoreId == storeId));
Then in your controller:
dbContext.Products.ProjectTo<ProductDto>(new { storeId = currentLoggedInStoreId });
AutoMapper will pass that parameter based on it matching "storeId" to your "Where" expression's variable at runtime.

Entity Framework identity column always zero

I'm using following class to insert products to database.
ID column is primary key.
After adding multiple products to db context (without calling savechanges method) all newly added rows identity columns are zero!
My scene...
User adds several products and browse them on the data grid.
User selects one product and adds some barcodes to selected product.
When user finishes the job clicks on save button and application calls SaveChanges method!
When user wants to add some barcodes to products firstly I need to find selected product from context and adds entered barcode text to Barcodes list. But I cant do that because all products identity columns value are the same and they are zero.
How can I solve this problem?
public class Product
{
public int ProductID { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public virtual List<Barcode> Barcodes { get; set; }
}
public class Barcode
{
public int BarcodeID { get; set; }
public string BarcodeText { get; set; }
public int ProductID { get; set; }
public virtual Product Product { get; set; }
}
Identity column value is assigned by database when you are inserting record into table. Before you call SaveChanges no queries are executed, nothing is passed to database and back. Context just keeps in-memory collection of entities with appropriate state (state defines which time of query should be executed during changes saving - for new entities, which have Added state, insert query should be generated and executed). So, ID stays with its default value, which is zero for integer. You should not give value manually. After inserting entities into database, context will receive ID value and update entity.
UPDATE: When you are adding Barcode to existing product, then EF is smart enough to update keys and foreign keys of entities:
var product = db.Products.First(); // some product from database
var barcode = new Barcode { BarcodeText = "000" };
// at this point barcode.ID and barcode.ProductID are zeros
product.Barcodes.Add(barcode);
db.SaveChanges(); // execute insert query
// at this point both PK and FK properties will be updated by EF

RavenDB index doesnt show new data

I have a model defined as
public class Department
{
[ScaffoldColumn(false)]
public object Id { get; set; }
[Required(ErrorMessage = "Department Name is required")]
[StringLength(25)]
[DisplayName("Department Name")]
public string Name { get; set; }
[DefaultValue(true)]
[DisplayName("Active?")]
public bool Active { get; set; }
}
i have added one record using the asp.net view. To retrieve the records i have created a simple index "DepartmentIndex" as
from dept in docs.Departments
select new {dept.Id,dept.Name}
To fetch the records I am using the following linq query
var depts = dbSession.Query<Department>("DepartmentIndex").OrderByDescending(x => x.Id);
Till here everything is fine. I can see the first record I have added on my view page. But, when I start adding more records i don't see the newly added ones. What have I missed?
RavenDB updates indexes in the background, so the results might be stale. See the documentation here for more info. In the client API you need to call the function WaitForNonStaleResults, to do this.
I was using build #133 i upgraded to #140 now, this doesn't seems to be a problem.