EF is overriding properties that i have set - c#-4.0

I'm using a EF 4.1 Code First setup, here are the entities.
public class Vendor
{
public int VendorId { get; set; }
public string Name { get; set; }
public virtual ICollection<VendorProduct> VendorProducts { get; set; }
}
public class VendorProduct
{
public int VendorProductId { get; set; }
public int ProductId { get; set; }
public int VendorId { get; set; }
public string VendorProductNumber { get; set; }
public int Quantity { get; set; }
public decimal SalesPrice { get; set; }
public Product Product { get; set; }
public Vendor Vendor { get; set; }
}
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
public string Manufacturer { get; set; }
public string ManufacturerNumber { get; set; }
public string UPC { get; set; }
public decimal SalesPrice { get; set; }
public string Description { get; set; }
public virtual ICollection<VendorProduct> VendorProducts { get; set; }
}
Here are the configurations
public class VendorConfiguration : EntityTypeConfiguration<Vendor>
{
public VendorConfiguration()
{
Property(p => p.Name).IsOptional().HasMaxLength(128);
}
}
public class ProductConfiguration : EntityTypeConfiguration<Product>
{
public ProductConfiguration()
{
//HasKey(p => p.ProductId);
//HasMany(p => p.Images).WithOptional();
Property(p => p.Name).IsOptional().HasMaxLength(128);
Property(p => p.Manufacturer).IsOptional().HasMaxLength(64);
Property(p => p.ManufacturerNumber).IsOptional().HasMaxLength(32);
Property(p => p.UPC).IsOptional().HasMaxLength(32);
Property(p => p.SalesPrice).IsOptional();
}
}
public VendorProductConfiguration()
{
//HasKey(v => v.VendorProductId);
Property(o => o.Quantity).IsRequired();
Property(o => o.SalesPrice).IsRequired();
Property(o => o.VendorId).IsRequired();
Property(o => o.ProductId).IsRequired();
Property(o => o.VendorProductNumber).IsOptional().HasMaxLength(50);
HasRequired(o => o.Product).WithMany(p => p.VendorProducts).HasForeignKey(o => o.ProductId).WillCascadeOnDelete(false);
}
Here is the DbContext.
public class UbidContext : DbContext
{
public IDbSet<Product> Products { get; set; }
public IDbSet<Vendor> Vendors { get; set; }
public IDbSet<VendorProduct> VendorProducts { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Add any configuration or mapping stuff here
modelBuilder.Configurations.Add(new VendorConfiguration());
modelBuilder.Configurations.Add(new VendorProductConfiguration());
modelBuilder.Configurations.Add(new ProductConfiguration());
}
public void Seed(UbidContext context)
{
//Create our indexes
context.Database.ExecuteSqlCommand("CREATE INDEX IX_Products_Name ON Products (Name)");
context.Database.ExecuteSqlCommand("CREATE INDEX IX_Products_Manufacturer ON Products (Manufacturer)");
context.Database.ExecuteSqlCommand("CREATE INDEX IX_Products_ManufacturerNumber ON Products (ManufacturerNumber)");
context.Database.ExecuteSqlCommand("CREATE INDEX IX_Products_UPC ON Products (UPC)");
//Add vendors to the database
AddVendors(context);
context.SaveChanges();
//Add products to the database
AddProducts(context);
context.SaveChanges();
//Add vendor products to the database
AddVendorProducts(context);
}
private static void AddVendors(UbidContext context)
{
new List<Vendor>
{
new Vendor()
{
Name = "TestVendor1",
},
new Vendor()
{
Name = "TestVendor2",
},
new Vendor()
{
Name = "TestVendor3",
}
}.ForEach(v => context.Vendors.Add(v));
}
private static void AddProducts(UbidContext context)
{
Image[] images = new Image[1];
images[0] = new Image
{
Url = "http://content.etilize.com/Thumbnail/10006997.jpg"
};
new List<Product>
{
new Product()
{
Manufacturer = "StarTech.com",
ManufacturerNumber = "SV211K",
Name = "StarTech.com SV211K KVM Switch - 2 x 1 - 2 x HD-15 Video",
UPC = "SV211K",
Images = images
},
new Product()
{
Manufacturer = "Targus Group International",
ManufacturerNumber = "CBT300",
Name = "Targus BlackTop Standard Notebook Case - Clamshell - Carrying Strap - 5 Pocket - Nylon - Black, Blue",
UPC = "CBT300"
},
new Product()
{
Manufacturer = "Lenovo Group Limited",
ManufacturerNumber = "31P8700",
Name = "Lenovo Optical ScrollPoint Pro Mouse - Optical - USB, PS/2",
UPC = "31P8700"
},
new Product()
{
Manufacturer = "Epson Corporation",
ManufacturerNumber = "C823071",
Name = "Epson Serial Interface Board with 32K Buffer - 1 x RS-232 Serial",
UPC = "C823071"
},
new Product()
{
Manufacturer = "Cisco Systems, Inc",
ManufacturerNumber = "WSX4013",
Name = "Cisco Catalyst 4000 Series Supervisor Engine II-Plus - 2 x GBIC, 1 x - Supervisor Engine",
UPC = "WSX4013"
}
}.ForEach(p => context.Products.Add(p));
}
private static void AddVendorProducts(UbidContext context)
{
Random random = new Random();
var vps = new List<VendorProduct>()
{
new VendorProduct()
{
ProductId = 1,
VendorId = 1,
Quantity = random.Next(3, 40),
SalesPrice = Converter.ConvertObjToDecimal(random.Next(20, 400)),
},
new VendorProduct()
{
ProductId = 2,
VendorId = 1,
Quantity = random.Next(3, 40),
SalesPrice = Converter.ConvertObjToDecimal(random.Next(20, 400)),
},
new VendorProduct()
{
ProductId = 3,
VendorId = 1,
Quantity = random.Next(3, 40),
SalesPrice = Converter.ConvertObjToDecimal(random.Next(20, 400)),
},
new VendorProduct()
{
ProductId = 4,
VendorId = 2,
Quantity = random.Next(3, 40),
SalesPrice = Converter.ConvertObjToDecimal(random.Next(20, 400)),
},
new VendorProduct()
{
ProductId = 4,
VendorId = 3,
Quantity = random.Next(3, 40),
SalesPrice = Converter.ConvertObjToDecimal(random.Next(20, 400)),
}
};
foreach (var vp in vps)
context.VendorProducts.Add(vp);
}
public class DropCreateIfChangeInitializer : DropCreateDatabaseIfModelChanges<UbidContext>
{
protected override void Seed(UbidContext context)
{
context.Seed(context);
base.Seed(context);
}
}
static UbidContext()
{
Database.SetInitializer<UbidContext>(new DropCreateIfChangeInitializer());
}
}
Now, what happens is that when it gets to the VendorProducts, the first one is added just fine, but the second one will not save because it looks like EF is not setting the Vendor object, the pattern that i see is that for each vendorproduct that is added if the vendorid and/or productid was used on a previous entity within the same context it will not populate the vendor or product so it sets it to null. As you can see from my code i am explicitly setting VendorId below, but when EF sends the data to the db, VendorId is null. If you need more info please let me know.
Thanks

I have copied and pasted your code into a console app with EF 4.1. When I run it I get this result in the database (SQL Server 2008 R2 Express):
I only have removed the stuff with the image and the Converter.ConvertObjToDecimal (didn't compile, I have directly used random.Next).
This is what one would expect from your code, I think. Do you get another result?

Related

Adding multiple classes to a shopping cart class .net mvc 5

I'm trying to come up with a car service booking application that allows one to either book a car into a service as well as buy a few parts, which is not essential, but I get an error that reads as follows:
SqlException: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_dbo.BasketLines_dbo.Parts_PartID". The conflict occurred in database "aspnet-Noir-20190224082924", table "dbo.Parts", column 'PartId'.
The statement has been terminated.
My classes are as follows:
PART
public class Part
{
[Key]
public int PartId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public byte[] ImageFile { get; set; }
public string ImageFilePath { get; set; }
public decimal Price { get; set; }
public virtual ICollection<ServicePartMapping>
ServicePartMappings { get; set;}
}
Service
public class Service
{
public int ServiceId { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public decimal Price { get; set; }
public ICollection<Part> Parts { get; set; }
}
ServicePartMapping
public class ServicePartMapping
{
public int ServicePartMappingID { get; set; }
public int PartNumber { get; set; }
public int? ServiceId { get; set; }
public int? ServicePartId { get; set; }
public virtual Service Service { get; set; }
public virtual ServicePart ServicePart { get;
set; }
}
Basket
public class Basket
{
public int Id { get; set; }
private string BasketID { get; set; }
private const string BasketSessionKey =
"BasketID";
private ApplicationDbContext db = new
ApplicationDbContext();
private string GetBasketID()
{
if
(HttpContext.Current.Session[BasketSessionKey]
== null)
{
if
(!string.IsNullOrWhiteSpace
(HttpContext.Current
.User.Identity.Name))
{
HttpContext.Current
.Session[BasketSessionKey] =
HttpContext.Current
.User.Identity.Name;
}
else
{
Guid tempBasketID = Guid.NewGuid()
HttpContext.Current
.Session[BasketSessionKey]
= tempBasketID.ToString();
}
}
return
HttpContext.Current
.Session[BasketSessionKey].ToString();
}
public static Basket GetBasket()
{
Basket basket = new Basket();
basket.BasketID = basket.GetBasketID();
return basket;
}
public void AddServiceToBasket(int serviceID,
int quantity)
{
var basketLine =
db.BasketLines.FirstOrDefault(b =>
b.BasketID == BasketID && b.ServiceID
== serviceID);
if (basketLine == null)
{
basketLine = new BasketLine
{
ServiceID = serviceID,
BasketID = BasketID,
Quantity = quantity,
DateCreated = DateTime.Now
};
db.BasketLines.Add(basketLine);
}
else
{
basketLine.Quantity += quantity;
}
db.SaveChanges();
}
public void AddPartToBasket(int partID, int
quantity)
{
var basketLine =
db.BasketLines.FirstOrDefault(b =>
b.BasketID == BasketID && b.PartId
== partID);
if (basketLine == null)
{
basketLine = new BasketLine
{
PartId = partID,
BasketID = BasketID,
Quantity = quantity,
DateCreated = DateTime.Now
};
db.BasketLines.Add(basketLine);
}
else
{
basketLine.Quantity += quantity;
}
db.SaveChanges();
}
public void RemoveLine(int ID)
{
var basketLine = db.BasketLines.FirstOrDefault(b => b.BasketID == BasketID && b.ServiceID
== ID || b.PartId == ID);
if (basketLine != null)
{
db.BasketLines.Remove(basketLine);
}
db.SaveChanges();
}
public void UpdateBasket(List<BasketLine> lines)
{
foreach (var line in lines)
{
var basketLine = db.BasketLines.FirstOrDefault(b => b.BasketID == BasketID &&
b.ServiceID == line.ServiceID);
if (basketLine != null)
{
if (line.Quantity == 0)
{
RemoveLine(line.ServiceID);
}
else
{
basketLine.Quantity = line.Quantity;
}
}
}
db.SaveChanges();
}
public void EmptyBasket()
{
var basketLines = db.BasketLines.Where(b => b.BasketID == BasketID);
foreach (var basketLine in basketLines)
{
db.BasketLines.Remove(basketLine);
}
db.SaveChanges();
}
public List<BasketLine> GetBasketLines()
{
return db.BasketLines.Where(b => b.BasketID == BasketID).ToList();
}
public decimal GetTotalCost()
{
decimal basketTotal = decimal.Zero;
decimal serviceTotal = decimal.Zero;
decimal partTotal = decimal.Zero;
if (GetBasketLines().Count > 0)
{
serviceTotal = db.BasketLines.Where(b => b.BasketID == BasketID).Sum(b => b.Service.Price
* b.Quantity);
partTotal = db.BasketLines.Where(b => b.BasketID == BasketID).Sum(b => b.Part.Price
* b.Quantity);
basketTotal = serviceTotal + partTotal;
}
return basketTotal;
}
public int GetNumberOfItems()
{
int numberOfItems = 0;
if (GetBasketLines().Count > 0)
{
numberOfItems = db.BasketLines.Where(b => b.BasketID == BasketID).Sum(b => b.Quantity);
}
return numberOfItems;
}
public void MigrateBasket(string userName)
{
//find the current basket and store it in memory using ToList()
var basket = db.BasketLines.Where(b => b.BasketID == BasketID).ToList();
//find if the user already has a basket or not and store it in memory using ToList()
var usersBasket = db.BasketLines.Where(b => b.BasketID == userName).ToList();
//if the user has a basket then add the current items to it
if (usersBasket != null)
{
//set the basketID to the username
string prevID = BasketID;
BasketID = userName;
//add the lines in anonymous basket to the user's basket
foreach (var line in basket)
{
AddServiceToBasket(line.ServiceID, line.Quantity);
AddPartToBasket(line.PartId, line.Quantity);
}
//delete the lines in the anonymous basket from the database
BasketID = prevID;
EmptyBasket();
}
else
{
//if the user does not have a basket then just migrate this one
foreach (var basketLine in basket)
{
basketLine.BasketID = userName;
}
db.SaveChanges();
}
HttpContext.Current.Session[BasketSessionKey] = userName;
}
public decimal CreateOrderLines(int orderID)
{
decimal orderTotal = 0;
var basketLines = GetBasketLines();
foreach (var item in basketLines)
{
BillLine BillLine = new BillLine
{
Service = item.Service,
ServiceID = item.ServiceID,
ServiceName = item.Service.Name,
Quantity = item.Quantity,
ServicePrice = item.Service.Price,
BillID = orderID
};
orderTotal += (item.Quantity * item.Service.Price);
db.BillLines.Add(BillLine);
}
db.SaveChanges();
EmptyBasket();
return orderTotal;
}
}
BasketLine
public class BasketLine
{
public int ID { get; set; }
public string BasketID { get; set; }
public int ServiceID { get; set; }
public int PartId { get; set; }
[Range(0, 50, ErrorMessage = "Please enter a quantity between 0 and 50")]
public int Quantity { get; set; }
public DateTime DateCreated { get; set; }
public virtual Service Service { get; set; }
public virtual Part Part { get; set; }
}
Assumed that EF Code First is used, the exception message indicates that you're using foreign key constraint inside BasketLines table which references PartId primary key column in Parts table, and you're trying to insert a value into BasketLines.PartId column which not exist in Parts table at this statement:
basketLine = new BasketLine
{
PartId = partID, // this assignment is the problem source
BasketID = BasketID,
Quantity = quantity,
DateCreated = DateTime.Now
};
db.BasketLines.Add(basketLine);
Based from inspection, you're trying to build relationship between Service, Part and BasketLine entities, therefore I suggested to add ForeignKeyAttribute for ServiceId and PartId property in BasketLine entity:
public class BasketLine
{
public int ID { get; set; }
public string BasketID { get; set; }
[ForeignKey("Service")]
public int ServiceID { get; set; }
[ForeignKey("Part")]
public int PartId { get; set; }
[Range(0, 50, ErrorMessage = "Please enter a quantity between 0 and 50")]
public int Quantity { get; set; }
public DateTime DateCreated { get; set; }
public virtual Service Service { get; set; }
public virtual Part Part { get; set; }
}
Additionally, since it's stated that a BasketLine requires Service with optional Part, you may also try modify OnModelCreating() method inside DbContext like this:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<BasketLine>()
.HasOptional(x => x.Part) // can save BasketLine without specifying Part
.WithRequired(x => x.Service); // cannot save BasketLine without using Service
}
Related issues:
Configure One-to-One Relationships in EF Code First
The INSERT statement conflicted with the FOREIGN KEY constraint

Why this is not working with AutoMapper?

I'm new in AutoMapper and I'm trying to map list to list in this way:
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public int Age { get; set; }
}
public class PersonMin
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<List<Person>, List<PersonMin>>();
});
IMapper iMapper = config.CreateMapper();
List<Person> source = new List<Person>
{
new Person { Id = 1, FirstName = "Bob", LastName = "Davis", Address = "Street1", Age = 40},
new Person { Id = 2, FirstName = "Rob", LastName = "Mavis", Address = "Street2", Age = 42}
};
List<PersonMin> destination = iMapper.Map<List<Person>, List<PersonMin>>(source);
foreach (var item in destination)
{
Console.WriteLine(item.Id + ", " + item.FirstName + ", " + item.LastName);
}
The destination is empty.
You don't need to care about the list.
Just simply map the models
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Person, PersonMin>();
});

Create a DropDown List from a db Entity MVC5

I want to create a dropdown list based on the contents of a db entity.
This seems like a simple enough concept but I can't really seem to pin it down.
Here's my code:
MODEL
public partial class Escuela
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Escuela()
{
this.Empleadoes = new HashSet<Empleado>();
}
public int ID { get; set; }
public string Nombre { get; set; }
public int PuestoID { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Empleado> Empleadoes { get; set; }
public virtual Puesto Puesto { get; set; }
}
public partial class ESCUELAEntities : DbContext
{
public ESCUELAEntities()
: base("name=ESCUELAEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Alumno> Alumnoes { get; set; }
public virtual DbSet<Empleado> Empleadoes { get; set; }
public virtual DbSet<Escuela> Escuelas { get; set; }
public virtual DbSet<Grupo> Grupoes { get; set; }
public virtual DbSet<Puesto> Puestoes { get; set; }
}
CONTROLLER
public ActionResult Index()
{
// HAVE TRIED THESE THREE
// #1
var EscQry = from d in db.Escuelas
select d.Nombre;
var escuelas = new SelectList(EscQry, "ID", "Nombre");
ViewData["esc"] = escuelas;
// #2
var escuelas = new SelectList(from d in db.Escuelas
select new SelectListItem { Text = d.Nombre, Value = d.ID.ToString() });
ViewData["esc"] = escuelas;
// #3
IEnumerable<Escuela> model = from p in db.Escuelas
select new Escuela { Nombre = p.Nombre };
// #1
return View();
// #2
return View();
// #3
return View(model);
}
VIEW
#model IEnumerable<_3E_III.Models.Escuela>
#{
ViewBag.Title = "Home Page";
}
#Html.DropDownList("Escuelas", ViewData["esc"] as List<SelectListItem>)
I get this error.
There is no ViewData item of type 'IEnumerable' that has the key 'Escuelas'.
I would make a View Model of the domain class, based on what properties I would need to show in my view.
public class EscuelaViewModel
{
public int ID { get; set; }
public string Nombre { get; set; }
public int PuestoID { get; set; }
.............. etc.
public Collection<SelectListItem> Escuelas {get; set;}
private static Collection<SelectListItem> CreateEscuelasOptions(string selectedOption == "")
{
var model = from p in db.Escuelas select new Escuela { Number = p.Nombre, Id= p.Id };
var options = new Collection<SelectListItem>();
foreach(var esc in model)
options.Add(new SelectListItem {Value = esc.Id, Text = esc.Number, Selected = selectedOption.Equals(esc.Number)});
return options;
}
public void LoadViewData()
{
Escuelas = CreateEscuelasOptions(Nombre);
}
}
Then, in the Controller:
public ActionResult Index()
{
var EscuelaViewModel = new EscuelaViewModel();
EscuelaViewModel.LoadViewData();
return View(EscuelaViewModel);
}
And the View:
#model EscuelaViewModel
#{
ViewBag.Title = "Home Page";
}
#Html.DropDownListFor(x => x.Nombre, Model.Escuelas, --Select option--)

How to add more Attribute in XElement?

I have a data structure as under
class BasketCondition
{
public List<Sku> SkuList { get; set; }
public string InnerBoolean { get; set; }
}
class Sku
{
public string SkuName { get; set; }
public int Quantity { get; set; }
public int PurchaseType { get; set; }
}
Now let us populate some value to it
var skuList = new List<Sku>();
skuList.Add(new Sku { SkuName = "TSBECE-AA", Quantity = 2, PurchaseType = 3 });
skuList.Add(new Sku { SkuName = "TSEECE-AA", Quantity = 5, PurchaseType = 3 });
BasketCondition bc = new BasketCondition();
bc.InnerBoolean = "OR";
bc.SkuList = skuList;
The desire output is
<BasketCondition>
<InnerBoolean Type="OR">
<SKUs Sku="TSBECE-AA" Quantity="2" PurchaseType="3"/>
<SKUs Sku="TSEECE-AA" Quantity="5" PurchaseType="3"/>
</InnerBoolean>
</BasketCondition>
My program so far is
XDocument doc =
new XDocument(
new XElement("BasketCondition",
new XElement("InnerBoolean", new XAttribute("Type", bc.InnerBoolean),
bc.SkuList.Select(x => new XElement("SKUs", new XAttribute("Sku", x.SkuName)))
)));
Which gives me the output as
<BasketCondition>
<InnerBoolean Type="OR">
<SKUs Sku="TSBECE-AA" />
<SKUs Sku="TSEECE-AA" />
</InnerBoolean>
</BasketCondition>
How can I add the rest of the attributes Quantity and PurchaseType to my program.
Please help
I found it
bc.SkuList.Select(x => new XElement("SKUs", new XAttribute("Sku", x.SkuName),
new XAttribute("Quantity", x.Quantity),
new XAttribute("PurchaseType", x.PurchaseType)
))
You can simply do this:
yourXElement.Add(new XAttribute("Quantity", "2"));
yourXElement.Add(new XAttribute("PurchaseType", "3"));

Selecting child projection from parent

Here are three classes in my domain:
public class Quote : IEntity, IAggregateRoot {
public int QuoteId { get; set; }
public IEnumerable<Price> Prices { get; set; }
}
public class Price : IEntity {
public int PriceId { get; set; }
public Carrier Carrier { get; set; }
public decimal? Price { get; set; }
public Quote Quote { get; set; }
}
public class Carrier : IEntity, IAggregateRoot {
public int CarrierId { get; set; }
public string Name { get; set; }
}
I want to be able to select a projection based on the Prices in the Quote. The return type should be an IEnumerable<[anonymous object]>. I have to start the query from the Quote because it is the root domain object. Here is what I have so far:
session.Linq<Quote>()
.Expand("Prices")
.Where(q => q.QuoteId == 1)
.Select(q => {
//this is where I don't know what to do.
//Maybe somthing like this:
return q.Prices.Select(p => {
new { CustomerName = p.Customer.Name, Price = p.Price }
});
});
The mappings would be:
Quote.Prices > HasMany (one-to-many)
Price.Quote > References (many-to-one)
Price.Carrier > References (one-to-one)
I found my answer. I completely forgot about the SelectMany Linq expression. Here is my solution.
session.Linq<Quote>()
.Where(q => q.QuoteId == 1)
.SelectMany(q => q.Prices, (q, p) => new { CustomerName = p.Customer.Name });

Resources