PetaPoco returns empty object - umbraco7

Inside my applocation, the petapoco poco returns an empty object (all values are null). Using the UI-O-Matic Nuget package inside my Umbraco 7.5.12.
The query i'm currently running:
var dbContext = ApplicationContext.Current.DatabaseContext;
var objects = dbContext.Database.Fetch<ObjectDB>("select Id, Name, CreatedOn, PlaceId, InActive, CityMapping, CountryIsoMapping, Globalsearch from ObjectsDB");
return objects.Where(n => n.PlaceId == PlaceId).FirstOrDefault();
TableDB is my PetaPoco model with the fields like:
[UIOMatic("ObjectsDB", "Object", "Object", FolderIcon = "icon-globe-inverted-europe-africa", ItemIcon = "icon-pin-location", RenderType = UIOMaticRenderType.List)]
[TableName("ObjectsDB")]
[PrimaryKey("Id", autoIncrement = false)]
[ExplicitColumns]
public class ObjectDB
{
[PrimaryKeyColumn(AutoIncrement = true)]
public int Id { get; set; }
[UIOMaticListViewFilter]
[UIOMaticListViewField(Name = "Name")]
[UIOMaticField(Name = "Name", Description = "Name")]
public string Name { get; set; }
}
When debuging:
`Debug result: con.Single<ObjectsDB>("select Name, Id from ObjectsDB where Id = 4")
This retruns the object:
{Umbraco.Extensions.Models.Custom.ObjectsModel.ObjectsDB} _createdOn: {1/1/0001 12:00:00 AM}
CityMapping: null
CountryIsoMapping: null
CreatedOn: {5/19/2017 4:22:16 PM}
Globalsearch: false
Id: 0
InActive: false
InCache: false
Name: null
Object: null
PlaceId: null `
Inserting data is working with the same dbContext, that's working.
What am I missing here?

I have used Petapoco in various Umbraco project and my approach is a bit different than your approach. I am sharing it here, hope it helps you.
This is the nuget package that I have used:(http://nuget.org/List/Packages/PetaPoco)
Please see my sample code below or in my blog:
[PetaPoco.TableName("fsCarts")]
[PetaPoco.PrimaryKey("RecordID")]
public class Cart
{
[Key]
public int RecordId { get; set; }
public string CartId { get; set; }
public Guid ProductId { get; set; }
public int Count { get; set; }
public DateTime DateCreated { get; set; }
}
UmbracoDatabase con = ApplicationContext.Current.DatabaseContext.Database;
public void AddToCart(Product product)
{
try
{
var cartItem = con.FirstOrDefault<Cart>("SELECT * FROM fsCarts WHERE CartID=#0 AND ProductID=#1", ShoppingCardId, product.ProductId);
if (cartItem == null)
{
cartItem = new Cart
{
ProductId = product.ProductId,
CartId = ShoppingCardId,
Count = 1,
DateCreated = DateTime.Now
};
con.Insert("fsCarts", "RecordID", cartItem);
}
else
{
cartItem.Count++;
con.Update("fsCarts", "RecordID", cartItem);
}
}
catch (Exception ex)
{
Elmah.ErrorLog.GetDefault(null).Log(new Elmah.Error(new Exception("Shopping Cart AddToCart: " + ex.ToString())));
}
}
////////////////////
public int RemoveFromCart(int id)
{
int itemCount = 0;
try
{
var cartItem = con.FirstOrDefault<Cart>("SELECT * FROM fsCarts WHERE CartID=#0 AND RecordId=#1", ShoppingCardId, id);
if (cartItem != null)
{
if (cartItem.Count > 1)
{
cartItem.Count--;
itemCount = cartItem.Count;
con.Update("fsCarts", "RecordID", cartItem);
}
else
{
con.Delete("fsCarts", "RecordID", cartItem);
}
}
}
catch (Exception ex)
{
Elmah.ErrorLog.GetDefault(null).Log(new Elmah.Error(new Exception("Shopping Cart RemoveFromCart: " + ex.ToString())));
}
return itemCount;
}
////////////////////
public List<Cart> GetCartItems()
{
List<Cart> cartItemList = new List<Cart>();
try
{
cartItemList = con.Query<Cart>("SELECT * FROM fsCarts WHERE CartID=#0", ShoppingCardId).ToList();
}
catch (Exception ex)
{
Elmah.ErrorLog.GetDefault(null).Log(new Elmah.Error(new Exception("Shopping Cart GetCartItems: " + ex.ToString())));
}
return cartItemList;
}
////////////////////
public decimal GetTotal()
{
decimal? total = null;
try
{
total = con.ExecuteScalar<decimal>("SELECT SUM(ISNULL(p.Price,0)*c.Count) FROM fsCarts c INNER JOIN fsProducts p ON c.ProductID=p.ProductID WHERE c.CartID=#0", ShoppingCardId);
}
catch (Exception ex)
{
Elmah.ErrorLog.GetDefault(null).Log(new Elmah.Error(new Exception("Shopping Cart GetTotal: " + ex.ToString())));
}
return total ?? decimal.Zero;
}

Removing the attribute [ExplicitColumns] above my class fixed the problem. No everything works as expected. Also the other decorations are working. So #Nurhak Kaya was partially right. After removing that attribute deleting the table and rebuild / generating the table.

Related

Permission Contacts in Xamarin Forms iOS

I met an error display when I tried to access user contact to fetch all contacts: The splash screen hide the permission dialog.
Did anyone meet this error before?
Interface:
public interface IUserContactsService
{
List<PhoneContactInfo> GetAllPhoneContacts(IEnumerable<int> filterIds = null);
}
UserContactService.cs:
[assembly: Dependency(typeof(UserContactService))]
namespace Test.iOS
{
public class PhoneContact
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string PhoneNumber { get; set; }
public string Name { get => $"{FirstName} {LastName}"; }
}
public class UserContactService : IUserContactsService
{
string phoneNumber(string number)
{
string callNumber = number;
int i = 0;
while (i < callNumber.Length)
{
if (callNumber[i] == ' ' || callNumber[i] == 160 || callNumber[i] == '-')
callNumber = callNumber.Remove(i, 1);
else
i++;
}
return callNumber;
}
public List<PhoneContactInfo> GetAllPhoneContacts(IEnumerable<int> filterIds = null)
{var keysTOFetch = new[] { CNContactKey.GivenName, CNContactKey.FamilyName, CNContactKey.EmailAddresses };
NSError error;
CNContact[] contactList;
var ContainerId = new CNContactStore().DefaultContainerIdentifier;
using (var predicate = CNContact.GetPredicateForContactsInContainer(ContainerId))
using (var store = new CNContactStore())
{
contactList = store.GetUnifiedContacts(predicate, keysTOFetch, out error);
}
var contacts = new List<PhoneContactInfo>();
foreach (var item in contactList)
{
if (null != item && null != item.EmailAddresses)
{
contacts.Add(new PhoneContactInfo
{
contactName = item.GivenName,
contactNumber = item.PhoneNumbers.ToString()
});
}
}
return contacts;
}
}
Here is my solution:
public List<PhoneContactInfo> GetAllPhoneContacts (IEnumerable<int> filterIds = null)
{
// if the app was not authorized then we need to ask permission
if (ABAddressBook.GetAuthorizationStatus() == ABAuthorizationStatus.Authorized)
{
GetContacts();
}
else Console.WriteLine("Error");
}

How could I read one to many linked table using link with Entity Framework?

I am new to Entity Framework and Linq (Visual Studio 2017 - EF 5.0) . Currently, I could read tables without issue but wonder how could I read a linked table.
My current functions do it but sure there is a simple way than two step reading that I have developed.
public override List<CartItem> GetMyCartOrderItems(int UserID)
{
try
{
using (foodorderingdbEntities oMConnection = new foodorderingdbEntities())
{
var oCart = oMConnection.carts.SingleOrDefault(p => p.USER_ID == UserID);
if (oCartItems != null)
{
int CartID = oCart.CART_ID;
var oCartItems = oMConnection.cart_item.Where(p => p.CART_ITEM_CART_ID == CartID);
if (oCartItems != null)
{
List<CartItem> oRecList = new List<CartItem>();
foreach (cart_item oDBrec in oCartItems)
{
CartItem oRec = new CartItem();
oRec.CartID = oDBrec.CART_ITEM_ID;
oRec.CartItemID = oDBrec.CART_ITEM_CART_ID;
oRec.DateTime = oDBrec.CART_ITEM_ADDED_DATE_TIME;
oRec.SystemComments = oDBrec.CART_ITEM_SYSTEM_COMMENTS;
oRecList.Add(oRec);
}
return oRecList;
}
else { return null; }
}
else { return null; }
}
}
catch (Exception ex)
{
//IBLogger.Write(LOG_OPTION.ERROR, "File : MHCMySQLDataConection.cs, Method : GetPatientByID(1), Exception Occured :" + ex.Message + Environment.NewLine + "Trace :" + ex.StackTrace);
return null;
}
}
You could see that I get Cart ID from Carts table using UserID and then I use the CartID retrieve cart Items from Cart_Item table. Cart_Item_Cart_ID is a foreign key in cart_item table. (This is a one to many table)
This is what I am thinking but obviously does not work.
List<cart_item> oCartItems = oMConnection.carts.SingleOrDefault(c => c.USER_ID == UserID).cart_item.Where(p => p.CART_ITEM_CART_ID = c.CART_ID).ToList<cart_item>();
Any help ?
My entity relation
public partial class cart
{
public cart()
{
this.cart_item = new HashSet<cart_item>();
}
public int CART_ID { get; set; }
public int USER_ID { get; set; }
public decimal ORDER_TOTAL_COST { get; set; }
public virtual ICollection<cart_item> cart_item { get; set; }
public virtual user user { get; set; }
}
Because your query has multiple levels of one to many relationships, and you just want the cart_items, it's easier to go the other way like this:
var oCart = oMConnection.cart_item
.Where(c=>c.cart.user.USER_ID == UserID);
Going the way you did should have worked as well, but you needed to use SelectMany instead of select like this:
var oCartItems = oMConnection.carts
.Where(c=>c.USER_ID==UserID)
.SelectMany(c=>c.cart_item);

Dynamic LINQ: Comparing Nested Data With Parent Property

I've a class with following structure:
public class BestWayContext
{
public Preference Preference { get; set; }
public DateTime DueDate { get; set; }
public List<ServiceRate> ServiceRate { get; set; }
}
public class ServiceRate
{
public int Id { get; set; }
public string Carrier { get; set; }
public string Service { get; set; }
public decimal Rate { get; set; }
public DateTime DeliveryDate { get; set; }
}
and I've dynamic linq expression string
"Preference != null && ServiceRate.Any(Carrier == Preference.Carrier)"
and I want to convert above string in Dynamic LINQ as follows:
var expression = System.Linq.Dynamic.DynamicExpression.ParseLambda<BestWayContext, bool>(condition, null).Compile();
But it showing following error:
Please correct me what am I doing wrong?
It looks like you wanted to do something like this:
var bwc = new BestWayContext
{
Preference = new Preference { Carrier = "test" },
DueDate = DateTime.Now,
ServiceRate = new List<ServiceRate>
{
new ServiceRate
{
Carrier = "test",
DeliveryDate = DateTime.Now,
Id = 2,
Rate = 100,
Service = "testService"
}
}
};
string condition = "Preference != null && ServiceRate.Any(Carrier == #0)";
var expression = System.Linq.Dynamic.DynamicExpression.ParseLambda<BestWayContext, bool>(condition, bwc.Preference.Carrier).Compile();
bool res = expression(bwc); // true
bwc.ServiceRate.First().Carrier = "test1"; // just for testing this -> there is only one so I've used first
res = expression(bwc); // false
You want to use Preference which belong to BestWayContext but you didn't tell the compiler about that. If i write your expression on Linq i will do as follows:
[List of BestWayContext].Where(f => f.Preference != null && f.ServiceRate.Where(g => g.Carrier == f.Preference.Carrier)
);
As you see i specified to use Preference of BestWayContext.

The Type of one of the Expression in the join clause is incorrect.Type inference failed in the call to join

Getting this error in GetDiseaseBySymptoms method below when trying to join two list of type DiseaseSymptomMapping & Symptom. Can anyhelp with better understanding suggest what went wrong with the code of GetDiseaseBySymptoms.
Note: Don't worry about the return type of GetDiseaseBySymptoms method, that will be taken care later once this issue is resolved.
class Program
{
static void Main(string[] args)
{
Disease malaria = new Disease { ID = 1, Name = "Malaria" };
Disease Cholera = new Disease { ID = 1, Name = "Cholera" };
Symptom Fever = new Symptom { ID = 1, Name = "Fever" };
Symptom Cough = new Symptom { ID = 2, Name = "Cough" };
Symptom Shevering = new Symptom { ID = 3, Name = "Shevering" };
List<DiseaseSymptomMapping> DiseaseDetails = new List<DiseaseSymptomMapping> {
new DiseaseSymptomMapping{ ID=1,disease=malaria,symptom=Fever},
new DiseaseSymptomMapping{ ID=2,disease=malaria,symptom=Shevering},
new DiseaseSymptomMapping{ ID=3,disease=Cholera,symptom=Fever},
new DiseaseSymptomMapping{ ID=4,disease=Cholera,symptom=Cough}
};
List<Symptom> symptoms = new List<Symptom> { Fever, Fever,Shevering };
List<Disease> diseases = GetDiseaseBySymptoms(symptoms, DiseaseDetails);
foreach (Disease disease in diseases)
{
Console.WriteLine("Disease Name :{0}", disease.Name);
}
Console.ReadLine();
}
class Disease
{
public int ID { get; set; }
public string Name { get; set; }
}
class Symptom
{
public int ID { get; set; }
public string Name { get; set; }
}
class DiseaseSymptomMapping
{
public int ID { get; set; }
public Disease disease { get; set; }
public Symptom symptom { get; set; }
}
static List<Disease> GetDiseaseBySymptoms(List<Symptom> symptoms,List<DiseaseSymptomMapping> DiseaseDetails)
{
var querytmp = from diseasedetails in DiseaseDetails
join symp in symptoms on diseasedetails.symptom equals symp in symptomsgrp
select new
{
DiseaseName= diseasedetails.Name,
Symptoms=symptomsgrp
};
foreach (var v in querytmp)
{
Console.WriteLine("{0}", v.DiseaseName);
}
return new List<Disease>();
}
}
Change in symptomsgrp to into symptomsgrp. And you get rid of the error by changing
DiseaseName = diseasedetails.Name
to
DiseaseName = diseasedetails.disease.Name

modify a TT template to add required html element

I am trying to create a t4 template to help speed up my Create Form template.
Is it possible to add extra html depending if a model's property is required?
e.g.
[Required]
[Display(Name = "Contact Email Address:")]
public string ContactEmailAddress { get; set; }
Now in my tt file do something like
foreach (ModelProperty property in GetModelProperties(mvcHost.ViewDataType)) {
if (!property.IsPrimaryKey && !property.IsReadOnly) {
#>
<div>
#Html.LabelFor(model => model.<#= property.Name #>)
#Html.EditorFor(model => model.<#= property.Name #>)
#Html.ValidationMessageFor(model => model.<#= property.Name #>)
if(this.Required==true){<span class="required-field"></span>}
</div>
<#
}
Or is this not possible?
1,Open this file:
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\Web\Mvc\Scaffolding\Templates\MvcViewWithContextScaffolder\ModelPropertyFunctions.include.t4
2, Add some property to ModelProperty
class ModelProperty {
public string Name { get; set; }
public string AssociationName { get; set; }
public string ValueExpression { get; set; }
public string ModelValueExpression { get; set; }
public string ItemValueExpression { get; set; }
public EnvDTE.CodeTypeRef Type { get; set; }
public bool IsPrimaryKey { get; set; }
public bool IsForeignKey { get; set; }//
public bool IsReadOnly { get; set; }//
public bool IsRequired{ get; set;}//Here is your customer Property
public bool Scaffold { get; set; }
}
3, Add an method out under this class
bool IsRequired(EnvDTE.CodeProperty propertyType)
{
foreach (EnvDTE.CodeAttribute attribute in propertyType.Attributes)
{
if (String.Equals(attribute.FullName, "System.ComponentModel.DataAnnotations.RequiredAttribute", StringComparison.Ordinal))
{
return true;
}
}
return false;
}
4,Go to the bottom of this file to modify the method GetEligibleProperties:
List<ModelProperty> GetEligibleProperties(EnvDTE.CodeType typeInfo) {
List<ModelProperty> results = new List<ModelProperty>();
if (typeInfo != null) {
foreach (var prop in typeInfo.GetPublicMembers().OfType<EnvDTE.CodeProperty>()) {
if (prop.HasPublicGetter() && !prop.IsIndexerProperty() && IsBindableType(prop.Type)) {
string valueExpression = GetValueExpressionSuffix(prop);
results.Add(new ModelProperty {
Name = prop.Name,
AssociationName = GetAssociationName(prop),
ValueExpression = valueExpression,
ModelValueExpression = "Model." + valueExpression,
ItemValueExpression = "item." + valueExpression,
Type = prop.Type,
IsPrimaryKey = IsPrimaryKey(prop),
IsForeignKey = IsForeignKey(prop),
IsRequired=IsRequired(prop),//Here is your customer property.
IsReadOnly = !prop.HasPublicSetter(),
Scaffold = Scaffold(prop)
});
}
}
}
return results;
}
5, go to the file
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\Web\Mvc\Scaffolding\Templates\MvcViewWithContextScaffolder\Edit.cs.t4
Add the following check before your ValidationMessageFor
#Html.ValidationMessageFor(model => model.<#= property.Name #>):
Codes like this:
<#
if (property.IsRequired) {
#>
*<!--your html code-->
<#
}
#>
This would be possible but would take more work than what you have here. You could add a Required property to ModelProperty and then set it by looking for the required attribute on the property when getting the model properties. You can take a look at the code that determines whether or not a property is a primary key in the .tt templates for an example.
If someone still searching for a solution...
I'm using the MetadataType attibute to define the property attributes like Required or DisplayName in a seperate class.
Sample:
[MetadataType(typeof(personMetaData))]
public partial class Person
{
}
public class personMetaData
{
[DisplayName("Surname")]
[Required]
public object Name { get; set; }
}
If you want to access these attributes in the t4-template you have to extend the ModelProperty class and creator in the template-file.
Put the following code at the bottom of your template (e.g. List.tt). You have to replace the existing code.
<#+
// Describes the information about a property on the model
public class ModelProperty
{
public string Name { get; set; }
public string ValueExpression { get; set; }
public Type UnderlyingType { get; set; }
public bool IsPrimaryKey { get; set; }
public bool IsReadOnly { get; set; }
public string DisplayName { get; set; }
}
// Change this list to include any non-primitive types you think should be eligible for display/edit
private static Type[] bindableNonPrimitiveTypes = new[]
{
typeof (string),
typeof (decimal),
typeof (Guid),
typeof (DateTime),
typeof (DateTimeOffset),
typeof (TimeSpan),
};
// Call this to get the list of properties in the model. Change this to modify or add your
// own default formatting for display values.
public List<ModelProperty> GetModelProperties(Type type)
{
List<ModelProperty> results = GetEligibleProperties(type);
foreach (ModelProperty prop in results)
{
if (prop.UnderlyingType == typeof (double) || prop.UnderlyingType == typeof (decimal))
{
prop.ValueExpression = "String.Format(\"{0:F}\", " + prop.ValueExpression + ")";
}
else if (prop.UnderlyingType == typeof (DateTime))
{
prop.ValueExpression = "String.Format(\"{0:g}\", " + prop.ValueExpression + ")";
}
}
return results;
}
// Call this to determine if the property represents a primary key. Change the
// code to change the definition of primary key.
private bool IsPrimaryKey(PropertyInfo property)
{
if (string.Equals(property.Name, "id", StringComparison.OrdinalIgnoreCase))
{
// EF Code First convention
return true;
}
if (string.Equals(property.Name, property.DeclaringType.Name + "id", StringComparison.OrdinalIgnoreCase))
{
// EF Code First convention
return true;
}
foreach (object attribute in property.GetCustomAttributes(true))
{
if (attribute is KeyAttribute)
{
// WCF RIA Services and EF Code First explicit
return true;
}
var edmScalar = attribute as EdmScalarPropertyAttribute;
if (edmScalar != null && edmScalar.EntityKeyProperty)
{
// EF traditional
return true;
}
/* var column = attribute as ColumnAttribute;
if (column != null && column.IsPrimaryKey)
{
// LINQ to SQL
return true;
}*/
}
return false;
}
// This will return the primary key property name, if and only if there is exactly
// one primary key. Returns null if there is no PK, or the PK is composite.
private string GetPrimaryKeyName(Type type)
{
IEnumerable<string> pkNames = GetPrimaryKeyNames(type);
return pkNames.Count() == 1 ? pkNames.First() : null;
}
// This will return all the primary key names. Will return an empty list if there are none.
private IEnumerable<string> GetPrimaryKeyNames(Type type)
{
return GetEligibleProperties(type).Where(mp => mp.IsPrimaryKey).Select(mp => mp.Name);
}
// Helper
private List<ModelProperty> GetEligibleProperties(Type type)
{
List<ModelProperty> results = new List<ModelProperty>();
foreach (PropertyInfo prop in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
Type underlyingType = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;
if (prop.GetGetMethod() != null && prop.GetIndexParameters().Length == 0 &&
IsBindableType(underlyingType))
{
var displayName = prop.Name;
// Search in Metadata
var metadata = type.GetCustomAttributes(typeof(MetadataTypeAttribute), true).OfType<MetadataTypeAttribute>().ToArray().FirstOrDefault();
if (metadata != null)
{
var metaPropery = metadata.MetadataClassType.GetProperty(prop.Name);
if (metaPropery != null)
{
displayName = ((DisplayNameAttribute)metaPropery.GetCustomAttributes(typeof (DisplayNameAttribute), true).First()).DisplayName;
}
}
results.Add(new ModelProperty
{
Name = prop.Name,
ValueExpression = "Model." + prop.Name,
UnderlyingType = underlyingType,
IsPrimaryKey = IsPrimaryKey(prop),
IsReadOnly = prop.GetSetMethod() == null,
DisplayName = displayName
});
}
}
return results;
}
// Helper
private bool IsBindableType(Type type)
{
return type.IsPrimitive || bindableNonPrimitiveTypes.Contains(type);
}
#>
Now you can access these attributes like this:
<#
List<ModelProperty> properties = GetModelProperties(mvcHost.ViewDataType);
foreach (ModelProperty property in properties) {
if (!property.IsPrimaryKey) {
#>
<th>
<#= property.DisplayName #><#= property.AllowEmptyStrings ? "*" : "" #>
</th>
<#
}
}
#>
T4 templates have changed with MVC5. To accomplish this in MVC5, I've written a tutorial here: https://johniekarr.wordpress.com/2015/05/16/mvc-5-t4-templates-and-view-model-property-attributes/

Resources