ASP.NET MVC class inheritence and LINQ - entity-framework

I'm having a problem with LINQ to entities which I've resolved, but want to make sure I've resolved in the right way.
I have 2 classes:
namespace ShopTest.Models
{
public class Shop
{
public int ShopID { get; set; }
public string Name { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Postcode { get; set; }
public string Country { get; set; }
public decimal Latitude { get; set; }
public decimal Longitude{ get; set; }
}
[NotMapped]
public class ShopLocation : Shop
{
public decimal AddressLatitude { get; set; }
public decimal AddressLongitude { get; set; }
public decimal DistanceFromAddress
{
get
{
return Convert.ToDecimal(
Math.Sqrt(
Math.Pow(Convert.ToDouble(this.Latitude - this.AddressLatitude), 2.0)
+
Math.Pow(Convert.ToDouble(this.Longitude- this.AddressLongitude), 2.0)
)
* 62.1371192
);
}
}
}
}
When querying in LINQ, I originally tried:
decimal lat = Convert.ToDecimal(-33.8736510, NumberFormatInfo.InvariantInfo);
decimal lng = Convert.ToDecimal(151.2068896, NumberFormatInfo.InvariantInfo);
var nearbyShops = from c in db.Shops
where Math.Abs(c.lat - lat) < 0.25M &&
Math.Abs(c.lng - lng) < 0.25M
select new NearbyShopLocation()
{
StoreNumber = store.StoreNumber,
Address = store.Address,
City = store.City,
Region = store.Region,
CountryCode = store.CountryCode,
PostalCode = store.PostalCode,
Latitude = store.Latitude,
Longitude = store.Longitude,
AddressLatitude = lat,
AddressLongitude = lng
};
var nearbySortedShops = nearbyShops.ToList().OrderBy(s => s.DistanceFromAddress).ToList();
However I kept getting the error "The entity or complex type 'ShopTest.Controllers.Shops' cannot be constructed in a LINQ to Entities query"
I've fixed the issue with the below code, but it doesn't make sense why this would work - being new to MVC I'm hoping someone can explain it. :-)
var nearbyShops = (from c in db.Shops
where Math.Abs(c.lat - lat) < 0.25M &&
Math.Abs(c.lng - lng) < 0.25M
select new
{
StoreNumber = c.StoreNumber,
Address = c.Address,
City = c.City,
Country = c.Country,
PostalCode = c.PostalCode,
Latitude = c.Latitude,
Longitude = c.Longitude,
}).ToList().Select(l => new ShopLocation
{
Name = l.Name,
City = l.City,
State = l.State,
Country = l.Country,
Lat = l.Lat,
Lng = l.Lng,
AddressLatitude = lat,
AddressLongitude = lng
}).ToList().OrderBy(s => s.DistanceFromAddress).ToList();
Have I done this correctly? Is there a better way?

EF has limitation that you cannot build mapped entity manually in the query. That means you cannot do this:
var shops = from s in db.Shops where ... select new Shop { ... };
This also involves derived entities. Because of that you first have to call ToList to switch to Linq-to-Objects:
var shopse = db.Shops.Where(...).ToList().Select(s => new Shop { ... });
Generally you should be OK with:
var nearbyShops =
(from c in db.Shops
where Math.Abs(c.lat - lat) < 0.25M &&
Math.Abs(c.lng - lng) < 0.25M
select c).ToList()
.Select(l => new ShopLocation
{
Name = l.Name,
City = l.City,
State = l.State,
Country = l.Country,
Lat = l.Lat,
Lng = l.Lng,
AddressLatitude = lat,
AddressLongitude = lng
}).OrderBy(s => s.DistanceFromAddress).ToList();

Related

LiteDb class deserialization is not working

I have B class that has a class A as member. The LiteDb store it correctly as I see in LiteDB Studio. "As" collection is also OK. Why is it not right in the deserialization? Class A has a BsonCtor. B also
namespace ConsoleAppTestDeserializatioBug {
class Program {
public class A {
public A() { A_ID = ObjectId.NewObjectId(); }
[BsonCtor]
public A(ObjectId id, string name) { A_ID = id; Name = name; }
[BsonId]
public ObjectId A_ID { get; set; }
public string Name { get; set; }
public const string CollectionName = "As";
}
public class B {
public const string CollectionName = "Bs";
public B() { B_ID = ObjectId.NewObjectId(); }
[BsonCtor]
public B(ObjectId id, int dummy, A a) { B_ID = id; Dummy = dummy; aObj = a;}
[BsonId]
public ObjectId B_ID { get; set; }
public int Dummy { get; set; }
[BsonRef(A.CollectionName)]
public A aObj { get; set; }
}
private LiteDatabase _LiteDatabase;
static void Main(string[] args) {
var p = new Program();
p.Test();
}
private void Test() {
A a = new A(); // Create my Object
a.Name = "Name123";
var initialId = a.A_ID;
B b = new B();
b.Dummy = 123;
b.aObj = a;
_LiteDatabase = new LiteDatabase(new ConnectionString(#"C:\Temp\tst1.db") { Connection = ConnectionType.Shared });
ILiteCollection<A> aas = _LiteDatabase.GetCollection<A>(A.CollectionName);
aas.Insert(a);
ILiteCollection<B> bs = _LiteDatabase.GetCollection<B>(B.CollectionName);
bs.Insert(b);
// Get in the DB
var bb = bs.FindAll().ToArray()[0];
var aa = bb.aObj;
var aaid = aa.A_ID;
if (aaid == initialId) { Console.WriteLine("Id is correct");}
var aname = aa.Name; // aname i s null!!!!! and why
}
}
}
I found an answer in LiteSB DbRef
I must just add an "include" in my query:
var bb = bs.Include(x => x.aObj).FindAll().ToArray()[0];

Spring Data MongoDB - filtering counting and summing sub-document arrays

Given a MongoDB collection described by the following classes:
#Document(collection = "persons")
#TypeAlias("person")
public class Person {
#Id
private ObjectId _id = null;
private String personName = null;
private List<Account> accountsList = null;
public ObjectId getId()
{
return _id;
}
public void setId(ObjectId id)
{
this._id = id;
}
public String getPersonName()
{
return personName;
}
public void setPersonName(String personName)
{
this.personName = personName;
}
public List<Account> getAccountsList()
{
return accountsList;
}
public void setAccountsList(List<Account> accountsList)
{
this.accountsList = accountsList;
}
}
public class Account
{
#Indexed(unique = false)
private double amount = 0.0;
private String description = null;
public double getAmount()
{
return amount;
}
public void setAmount(double amount)
{
this.amount = amount;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
}
Using Spring Data Mongodb, how do I:
1) count the number of accounts only where the amount > x
2) retrieve only the accounts where the amount > x
3) sum the total amount of accounts only where the amount > x
Any help will be appreciated

How to define string arrays in Data Contract?

I have a string array in datacontract as below
[DataMember(Name = "photos", IsRequired = true, Order = 3)]
public string[] photos { get; set; }
In WCF REST Service call I am passing below xml input for this string array
<photos>
<string>http://localhost:13169/MainPortal/ContentLibrary/21/58/1227132014-bmw-x1_100426158_m.jpg</string>
<string>http://localhost:13169/MainPortal/ContentLibrary/21/58/122713bmw2.jpg</string>
<string>http://localhost:13169/MainPortal/ContentLibrary/21/58/122713bmw3.jpg</string>
<string>http://localhost:13169/MainPortal/ContentLibrary/21/58/122713BMW_Hamann_Laguna_Seca.jpg</string><string>http://localhost:13169/MainPortal/ContentLibrary/21/58/1227132014-BMW-X1-SUV-sDrive-28i-4dr-4x2-Sports-Activity-Vehicle-Exterior-2.png</string>
</photos>
My client code able to make WebService call with passing xml in HttpWebRequest without any issues, from the service I could see all other data coming in except this string array. Am I missing something in DataContract to serialize arrays. Please help
Tried with CollectionDataContract as below still no luck
[CollectionDataContract(Name = "photos")]
public class Photos : Collection<string>
Also added KnownTypes which is however not required for ordinal types
[KnownType(typeof(string[]))]
public class PublishPhotos
{
Here is complete data contract class
[DataContract(Namespace = "http://myurl.com/Publisher")]
[KnownType(typeof(string[]))]
public class PublishPhotos
{
[DataMember(Name = "publicationId", IsRequired = true, Order = 0)]
public int publicationId { get; set; }
[DataMember(Name = "issueId", IsRequired = true, Order = 1)]
public string issueId { get; set; }
[DataMember(Name = "contentId", IsRequired = true, Order = 2)]
public string contentId { get; set; }
[DataMember(Name = "photos", IsRequired = true, Order = 3)]
public Photos photos { get; set; }
}
Finally I figured out what went wrong with XML in HttpWebRequest, the issue is with serializing string array. The easiest way I could have figured out through visiting /PublisherSvc.svc/help for string it requires namespace http://schemas.microsoft.com/2003/10/Serialization/Arrays as below
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">http://localhost:8081/photos/1/1.jpg</string>
Hope this helps someone facing similar issue
I have figured out the answer to this problem. Thanks to #HarlanB
I have changed data contract from DataContract Serialization to XmlSerialization
[SerializableAttribute()]
[XmlTypeAttribute(AnonymousType = true)]
[XmlRootAttribute(Namespace = "http://myUrl.com/Publisher", IsNullable = false)]
public class PublishPhotos
{
//[DataMember(Name = "publicationId", IsRequired = true, Order = 0)]
[XmlElementAttribute(ElementName="publicationId", Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 0)]
public int publicationId { get; set; }
//[DataMember(Name = "issueId", IsRequired = true, Order = 1)]
[XmlElementAttribute(ElementName = "issueId", Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 1)]
public string issueId { get; set; }
//[DataMember(Name = "contentId", IsRequired = true, Order = 2)]
[XmlElementAttribute(ElementName = "contentId", Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 2)]
public string contentId { get; set; }
//[DataMember(Name = "photos", IsRequired = true, Order = 3)]
[XmlElementAttribute(ElementName = "photos", Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 3)]
public string[] photos { get; set; }
}
In client code I am using XmlSerializer to write to HttpWebRequest as below
pubPhotos.publicationId = Convert.ToInt32(publication.Value);
pubPhotos.issueId = secName;
pubPhotos.contentId = selectedMediaItem;
HtmlDocument divDoc = new HtmlDocument();
divDoc.LoadHtml(widgetScript);
HtmlNode divNode = divDoc.DocumentNode.FirstChild;
HtmlNodeCollection imgs = divNode.SelectNodes("//img");
Collection<string> photos = new Collection<string>();
foreach (HtmlNode img in imgs)
{
photos.Add(img.Attributes["src"].Value);
}
pubPhotos.photos = photos.ToArray();
HttpWebRequest req = null;
const string url = "http://localhost:40009/PublisherSvc.svc/PublishPhotos";
req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "POST";
req.ContentType = "application/xml; charset=utf-8";
req.KeepAlive = false;
req.Timeout = 30000;
req.Headers.Add("SOAPAction", url);
XmlSerializer serilizer = new XmlSerializer(typeof(PublishPhotos));
var sw = new StreamWriter(req.GetRequestStream());
serilizer.Serialize(sw, pubPhotos);
sw.Close();
I hope this helps some other people out there that are having similar problems.

How to add & update within entity framework

my Model Entity FrameWork :
public partial class T02
{
public long ID { get; set; }
public int F01 { get; set; }
}
Table : T02
------------------------
id[Key,identity] F01
------------------------
1 a
2 b
====================================================
i have a button > Code
public void Button_Click(object Sender, EventArgs e)
{
T02 T1 = new T02 { ID = 1, F01 = "x" };
T02 T2 = new T02 { ID = 2, F01 = "y" };
T02 T3 = new T02 { ID = 0, F01 = "g" };
T02 T4 = new T02 { ID = 0, F01 = "h" };
// How ID > 1 2 Update in Table &
// because not in table, > g , h > automatic add to Table
// ???
}
my problem is : i not ontime update and if T02.ID not on the table automatic added..
Is it possible that I do added to table Records Without id and i do Update Records With id
i worked c#.NET 4.5 . Thanks
Add this method to your Context class:
protected virtual void InsertOrUpdate<T>(T entity, long id)
{
if (id == default(int))
this.Set<T>().Add(entity);
else
this.Entry(entity).State = EntityState.Modified;
}
Which can be used something like this:
public void Button_Click(object Sender, EventArgs e)
{
T02 T1 = new T02 { ID = 1, F01 = "x" };
T02 T2 = new T02 { ID = 2, F01 = "y" };
T02 T3 = new T02 { ID = 0, F01 = "g" };
T02 T4 = new T02 { ID = 0, F01 = "h" };
using(var context = new MyDbContext())
{
context.InsertOrUpdate(T1, T1.ID);
context.InsertOrUpdate(T2, T2.ID);
context.InsertOrUpdate(T3, T3.ID);
context.InsertOrUpdate(T4, T4.ID);
}
}
Once this is working you can consider implementing a standard interface across all of your POCO classes that exposes the ID property so that you no longer have to pass ID into the method:
public interface IId
{
long ID { get; }
}
public partial class T02 : IId
{
public long ID { get; set; }
public int F01 { get; set; }
}
which gives you a neater method in your Context
protected virtual void InsertOrUpdate<T>(T entity) where T : IId
{
if (entity.ID == default(int))
this.Set<T>().Add(entity);
else
this.Entry(entity).State = EntityState.Modified;
}

EclipseLink GeneratedValue null on postgres only on one entity

I have a rather weird case. I have some entities generated with netbeans and i can persist all except one. I see no difference in the database nor in the entity class. Can someone help me, here is my entity class , database, and error that i am receiving
CREATE TABLE objekat
(
id_objekat bigserial NOT NULL,
id_opstina serial NOT NULL,
naziv character varying(50) NOT NULL,
kapacitet character varying(50),
adresa character varying(100),
lokacija_sirina double precision,
lokacija_duzina double precision,
opis character varying(500),
korisnicko_ime character varying(50),
sifra character varying(50),
maks_broj_slike integer,
absolute_path_logo character varying(255),
CONSTRAINT objekat_pkey PRIMARY KEY (id_objekat),
CONSTRAINT fkobjekat924176 FOREIGN KEY (id_opstina)
REFERENCES opstina (id_opstina) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
and this is my entity bean.
#Entity
#Table(name = "objekat")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Objekat.findAll", query = "SELECT o FROM Objekat o"),
#NamedQuery(name = "Objekat.findByIdObjekat", query = "SELECT o FROM Objekat o WHERE o.idObjekat = :idObjekat"),
#NamedQuery(name = "Objekat.findByNaziv", query = "SELECT o FROM Objekat o WHERE upper (o.naziv) like upper(:naziv)"),
#NamedQuery(name = "Objekat.findByNazivAndOpstina", query = "SELECT o FROM Objekat o inner join o.idOpstina op WHERE upper (o.naziv) like upper(:naziv) and op.idOpstina = :idOpstina"),
#NamedQuery(name = "Objekat.findByKapacitet", query = "SELECT o FROM Objekat o WHERE o.kapacitet = :kapacitet"),
#NamedQuery(name = "Objekat.findByAdresa", query = "SELECT o FROM Objekat o WHERE o.adresa = :adresa"),
#NamedQuery(name = "Objekat.findByLokacijaSirina", query = "SELECT o FROM Objekat o WHERE o.lokacijaSirina = :lokacijaSirina"),
#NamedQuery(name = "Objekat.findByLokacijaDuzina", query = "SELECT o FROM Objekat o WHERE o.lokacijaDuzina = :lokacijaDuzina")})
public class Objekat implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id_objekat",columnDefinition = "BIGSERIAL")
private Long idObjekat;
#Size(max = 255)
#Column(name = "absolute_path_logo")
private String absolutePathLogo;
#OneToMany( mappedBy = "objekatidObjekat")
private List<DogadjajObjekat> dogadjajObjekatList;
#OneToMany( mappedBy = "objekatidObjekat")
private List<SlikeLokacijaObjekat> slikeLokacijaObjekatList;
#OneToMany( mappedBy = "idObjekat")
private List<RasporedObjekat> rasporedObjekatList;
#Column(name = "maks_broj_slike")
private Integer maksBrojSlike;
#Size(max = 50)
#Column(name = "korisnicko_ime")
private String korisnickoIme;
#Size(max = 50)
#Column(name = "sifra")
private String sifra;
#Size(max = 500)
#Column(name = "opis")
private String opis;
// #Max(value=?) #Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
#Column(name = "lokacija_sirina")
private Double lokacijaSirina;
#Column(name = "lokacija_duzina")
private Double lokacijaDuzina;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 50)
#Column(name = "naziv")
private String naziv;
#Size(max = 50)
#Column(name = "kapacitet")
private String kapacitet;
#Size(max = 100)
#Column(name = "adresa")
private String adresa;
#JoinTable(name = "tip_objekta_objekat", joinColumns = {
#JoinColumn(name = "objekatid_objekat", referencedColumnName = "id_objekat")}, inverseJoinColumns = {
#JoinColumn(name = "tip_objektaid_tip_objekta", referencedColumnName = "id_tip_objekta")})
#ManyToMany
private List<TipObjekta> tipObjektaList;
#JoinColumn(name = "id_opstina", referencedColumnName = "id_opstina")
#ManyToOne(optional = false)
private Opstina idOpstina;
public Objekat() {
}
public Objekat(Long idObjekat) {
this.idObjekat = idObjekat;
}
public Objekat(Long idObjekat, String naziv) {
this.idObjekat = idObjekat;
this.naziv = naziv;
}
public Long getIdObjekat() {
return idObjekat;
}
public void setIdObjekat(Long idObjekat) {
this.idObjekat = idObjekat;
}
public String getNaziv() {
return naziv;
}
public void setNaziv(String naziv) {
this.naziv = naziv;
}
public String getKapacitet() {
return kapacitet;
}
public void setKapacitet(String kapacitet) {
this.kapacitet = kapacitet;
}
public String getAdresa() {
return adresa;
}
public void setAdresa(String adresa) {
this.adresa = adresa;
}
#XmlTransient
public List<TipObjekta> getTipObjektaList() {
return tipObjektaList;
}
public void setTipObjektaList(List<TipObjekta> tipObjektaList) {
this.tipObjektaList = tipObjektaList;
}
public Opstina getIdOpstina() {
return idOpstina;
}
public void setIdOpstina(Opstina idOpstina) {
this.idOpstina = idOpstina;
}
#Override
public int hashCode() {
int hash = 0;
hash += (idObjekat != null ? idObjekat.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Objekat)) {
return false;
}
Objekat other = (Objekat) object;
if ((this.idObjekat == null && other.idObjekat != null) || (this.idObjekat != null && !this.idObjekat.equals(other.idObjekat))) {
return false;
}
return true;
}
#Override
public String toString() {
return "rs.dzetSet.entiteti.Objekat[ idObjekat=" + idObjekat + " ]";
}
public String getOpis() {
return opis;
}
public void setOpis(String opis) {
this.opis = opis;
}
public Double getLokacijaSirina() {
return lokacijaSirina;
}
public void setLokacijaSirina(Double lokacijaSirina) {
this.lokacijaSirina = lokacijaSirina;
}
public Double getLokacijaDuzina() {
return lokacijaDuzina;
}
public void setLokacijaDuzina(Double lokacijaDuzina) {
this.lokacijaDuzina = lokacijaDuzina;
}
public String getKorisnickoIme() {
return korisnickoIme;
}
public void setKorisnickoIme(String korisnickoIme) {
this.korisnickoIme = korisnickoIme;
}
public String getSifra() {
return sifra;
}
public void setSifra(String sifra) {
this.sifra = sifra;
}
public Integer getMaksBrojSlike() {
return maksBrojSlike;
}
public void setMaksBrojSlike(Integer maksBrojSlike) {
this.maksBrojSlike = maksBrojSlike;
}
public void pocevajMaksBrojSlike(){
this.maksBrojSlike++;
}
public String getAbsolutePathLogo() {
return absolutePathLogo;
}
public void setAbsolutePathLogo(String absolutePathLogo) {
this.absolutePathLogo = absolutePathLogo;
}
#XmlTransient
public List<RasporedObjekat> rasporedObjekatListPrePodne(){
List<RasporedObjekat> rez = new ArrayList<RasporedObjekat>();
if(rasporedObjekatList==null){
rasporedObjekatList = new ArrayList<RasporedObjekat>();
}
for(RasporedObjekat ro:rasporedObjekatList){
if(!ro.getVecernjiProgram()){
rez.add(ro);
}
}
return rez;
}
#XmlTransient
public List<RasporedObjekat> rasporedObjekatListPoslePodne(){
List<RasporedObjekat> rez = new ArrayList<RasporedObjekat>();
if(rasporedObjekatList==null){
rasporedObjekatList = new ArrayList<RasporedObjekat>();
}
for(RasporedObjekat ro:rasporedObjekatList){
if(ro.getVecernjiProgram()){
rez.add(ro);
}
}
return rez;
}
#XmlTransient
public List<DogadjajObjekat> getDogadjajObjekatList() {
return dogadjajObjekatList;
}
public void setDogadjajObjekatList(List<DogadjajObjekat> dogadjajObjekatList) {
this.dogadjajObjekatList = dogadjajObjekatList;
}
#XmlTransient
public List<SlikeLokacijaObjekat> getSlikeLokacijaObjekatList() {
return slikeLokacijaObjekatList;
}
public void setSlikeLokacijaObjekatList(List<SlikeLokacijaObjekat> slikeLokacijaObjekatList) {
this.slikeLokacijaObjekatList = slikeLokacijaObjekatList;
}
#XmlTransient
public List<RasporedObjekat> getRasporedObjekatList() {
return rasporedObjekatList;
}
public void setRasporedObjekatList(List<RasporedObjekat> rasporedObjekatList) {
this.rasporedObjekatList = rasporedObjekatList;
}
and i persist it in a rather normal way, or i just think so.
utx.begin();
if(noviObjekat.getIdObjekat() == null){
em.persist(noviObjekat);
}else{
em.merge(noviObjekat);
}
utx.commit();
and i get a pretty weird error
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: null value in column "id_opstina" violates not-null constraint
Error Code: 0
Call: INSERT INTO objekat (absolute_path_logo, adresa, kapacitet, korisnicko_ime, lokacija_duzina, lokacija_sirina, maks_broj_slike, naziv, opis, sifra, id_opstina) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
bind => [11 parameters bound]
Query: InsertObjectQuery(rs.dzetSet.entiteti.Objekat[ idObjekat=null ])
}
You set a generator on the field for "id_objekat" but the exception is for the not-null constraint on "id_opstina". You will need to set this field yourself or use a returning policy to get it instead:
http://wiki.eclipse.org/Using_EclipseLink_JPA_Extensions_(ELUG)#Using_EclipseLink_JPA_Extensions_for_Returning_Policy