Custom reference naming convention in ormlite - servicestack

Is there a way to change the default {PropertyReference}Id naming convention for references and foreign keys ?
For example, I want to do this :
public class Customer
{
[References(typeof(CustomerAddress))]
public int Id_PrimaryAddress { get; set; } // with a prefix
[Reference]
public CustomerAddress PrimaryAddress { get; set; }
}
instead of that :
public class Customer
{
[References(typeof(CustomerAddress))]
public int PrimaryAddressId { get; set; } // standard
[Reference]
public CustomerAddress PrimaryAddress { get; set; }
}
Thank you

You can't change the code convention of OrmLite's Reference Conventions globally, but you can use the [Alias("DbColumnName")] to map it to a different underlying RDBMS Table column.
Overriding Conventions with Attributes
You're also able to use the Foreign Key and References Attributes as your example does to override the conventions, e.g. you can play with this Live Example on Gistlyn:
public class CustomerAddress
{
[AutoIncrement]
public int Id { get; set; }
public string Address { get; set; }
public string Country { get; set; }
}
public class Customer
{
[AutoIncrement]
public int Id { get; set; }
public string Name { get; set; }
[References(typeof(CustomerAddress))]
public int Id_PrimaryAddress { get; set; } // with a prefix
[Reference]
public CustomerAddress PrimaryAddress { get; set; }
}
db.CreateTable<Customer>();
db.CreateTable<CustomerAddress>();
var customer = new Customer
{
Name = "The Customer",
PrimaryAddress = new CustomerAddress {
Address = "1 Home Street",
Country = "US"
},
};
db.Save(customer, references:true);
Where you can load it and its references and view it with:
var c = db.LoadSelect<Customer>(x => x.Name == "The Customer");
c.PrintDump();
Which will output:
[
{
Id: 1,
Name: The Customer,
Id_PrimaryAddress: 1,
PrimaryAddress:
{
Id: 1,
Address: 1 Home Street,
Country: US
}
}
]

Related

How to use AutoMapper to create mapping from single class to nested class

My class structure looks like this. What I'm trying to do is, create automap from source EmployeeInfo class to destination NewEmployeeInfo class and vise Versa.
public class EmployeeInfo ///// Old Employee class - Transform this into New
{
public int EmployeeID { get; set; }
public string EmployeeName { get; set; }
public int DepartmentID { get; set; }
public string DepartmentName { get; set; }
}
public class NewEmployeeInfo //// New Employee -- Transform in to this
{
public Employee Employee { get; set; }
public Department Department { get; set; }
}
public class Employee
{
public int EmployeeID { get; set; }
public string EmployeeName { get; set; }
}
public class Department
{
public int DepartmentID { get; set; }
public string DepartmentName { get; set; }
}

EntityFramework : Invalid column name *_ID1

I am trying to implement DbContext for couple of tables called 'Employee' and 'Department'
Relationship between Employee and Department is many to one. i.e. department can have many employees.
Below are the EntityFramework classes I designed ( CodeFirst approach )
[Table("Employee")]
public class Employee
{
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Column("Name")]
public string Name { get; set; }
[Column("Department_ID")]
public int Department_ID { get; set; }
public virtual Department Department { get; set; }
}
[Table("Department")]
public class Department
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[Column("Name")]
public string Name { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
While adding Employee record I am getting below exception
"Invalid column name 'Department_ID1'."
I am not sure why EF is referring to Department_ID1. Do I need to add configuration in OnModelCreating method of DbContext?
I am using EF version 6.1.1
I've also gotten this problem in my EF one-many deals where the one has a List of the many property and my mapping didn't specify that property. For example take:
public class Notification
{
public long ID { get; set; }
public IList<NotificationRecipient> Recipients { get; set; }
}
then
public class NotificationRecipient
{
public long ID { get; set; }
public long NotificationID { get; set; }
public Notification Notification { get; set; }
}
Then in my mapping, the way that caused the Exception (the incorrect way):
builder.HasOne(x => x.Notification).WithMany()
.HasForeignKey(x => x.NotificationID);
What fixed it (the correct way) was specifying the WithMany property:
builder.HasOne(x => x.Notification).WithMany(x => x.Recipients)
.HasForeignKey(x => x.NotificationID);
Hi After spending some time I could fix this problem by using ForeignKey attribute on public virtual Department Department { get; set; } property of Employee class.
Please see below code.
[Table("Employee")]
public class Employee
{
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Column("Name")]
public string Name { get; set; }
[Column("Department_ID")]
public int Department_ID { get; set; }
[ForeignKey("Department_ID")]
public virtual Department Department { get; set; }
}
This fixed my problem. Are there any other solution to fix this? Using fluent API?
For me, the issue was resolved by removing a (duplicate?) virtual property.
Using the OP's example:
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public int Department_ID { get; set; }
public virtual Department Department { get; set; }
}
public class Department
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
Turns into:
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public int Department_ID { get; set; }
}
public class Department
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
In my case I added a virtual property on top of the auto generated property
I fixed it by adding the NotMapped attribute to my property, or you could configure with fluent api
public partial class Control
{
[NotMapped]
public virtual ICollection<Control> Children { get => this.InverseParent; set => this.InverseParent = value; }
}
I had the same error, my issue was the FK was a long but I had it as an int in the model. EF generated a new column because it didn't match types on the FK so it assumed they weren't the same and went ahead with making another one but putting 1 at the end because there was already one with the proper name. Making sure the types matched resolved the issue for me.
This can be fixed simply by putting [NotMapped] annotation on your virtual properties.
public class Employee
{
[ForeignKey("Department")]
public int Department_ID
[NotMapped]
public virtual Department Department { get; set; }
}
And in you modelBuilder:
modelBuilder.Entity<Employee>(entity =>
{
entity.HasOne(e => e.Department);
});
Just flip this around if you want to call by Department.
We use the [NotMapped] annotation so that EF Core will disregard it when looking at your database.

Entity Framework - Update complex entities

I'm using EF5.0 (database first) and trying to Update "Company" entity which is a complex type, it contains "Address" entity as navigation property.
I receive a Company DTO object from UI and I map it, using AutoMapper, to Entity object and call objectContext.Save() for saving.
Problem am facing is, "Company" entity values are getting saved but not the "Address" entity. Below are the each object details-
public class CompanyDto
{
public int Id { get; set; }
public string Name { get; set; }
public AddressDto Address { get; set; }
}
with AddressDto as -
public class AddressDto : IDto
{
public int Id { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string PostCode { get; set; }
}
Company Entity (generated by EF - database first)
public partial class tblCompany
{
public tblCompany()
{
this.tblAddresses = new HashSet<tblAddress>();
}
public int ID { get; set; }
public string CompanyName { get; set; }
public virtual ICollection<tblAddress> tblAddresses { get; set; } //navigation property
}
with Address entity is as follows -
public partial class tblAddress
{
public int ID { get; set; }
public int CaseID { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string City { get; set; }
public string County { get; set; }
public string PostCode { get; set; }
public virtual tblCase tblCase { get; set; }
}
AutoMapper mapping configuration for converting from DTO to entity
Mapper.CreateMap<CompanyDto, tblCase>()
.ForMember(x => x.ID, opt => opt.MapFrom(cd => cd.Id))
.ForMember(x => x.CompanyName, opt => opt.MapFrom(cd => cd.Name))
.AfterMap((s, d) => d.tblAddresses.Add(new tblAddress
{
AddressLine1 = s.Address.Street,
CaseID = s.Id,
City = s.Address.City,
PostCode = s.Address.PostCode
}));
public void Update(CompanyDto company)
{
//TO DO: check if AutoMapper could map address as well.
var companyDao = Mapper.Map<CompanyDto, tblCase>(company);
_companyRepository.Update(companyDao);
_unitOfWork.Save();
}
Thanks in advance
Sai

Cannot serialize inherited property into JSON via Json.Net

I am using C# .NET 4.0 and Newtonsoft JSON 4.5.0.11
[JsonObject(MemberSerialization.OptIn)]
public interface IProduct
{
[JsonProperty(PropertyName = "ProductId")]
int Id { get; set; }
[JsonProperty]
string Name { get; set; }
}
public abstract class BaseEntity<T>
{
private object _id;
public T Id
{
get { return (T)_id; }
set { _id = value; }
}
}
public class Product : BaseEntity<int>, IProduct
{
public string Name { get; set; }
public int Quantity { get; set; }
}
I need to serialize part of object and I use interfaces with declared concrete properties to do this.
The serialization looks like:
Product product = new Product { Id = 1, Name = "My Product", Quantity = 5};
JsonConvert.SerializeObject(product);
Expected result is:
{"ProductId": 1, "Name": "My Product"}
But actual result is:
{"Name": "My Product"}
How can I serialize this object correctly?
UPD: Looked at the source code of json.net and came to the conclusion that this is a bug with grab information about object through ReflectionUtils.
Have you tried this?
public interface IProduct
{
int Id { get; set; }
string Name { get; set; }
}
[JsonObject(MemberSerialization.OptIn)]
public abstract class BaseEntity<T>
{
private object _id;
[JsonProperty]
public T Id
{
get { return (T)_id; }
set { _id = value; }
}
}
[JsonObject(MemberSerialization.OptIn)]
public class Product : BaseEntity<int>, IProduct
{
[JsonProperty]
public string Name { get; set; }
[JsonProperty]
public int Quantity { get; set; }
}

ServiceStack.OrmLite - how to include field from foreign key lookup?

I'm trying out the ServiceStack MVC PowerPack, and am trying the included OrmLite ORM and am trying to get data from a table referenced by a foreign key without any idea how to do so.
In the OrmLite examples that use the Northwind database, for example, would it be possible to return a Shipper object that included the "ShipperTypeName" as a string looked up through the foreign key "ShipperTypeID"?
From http://www.servicestack.net/docs/ormlite/ormlite-overview, I'd like to add the ShipperName field to the Shipper class if possible:
[Alias("Shippers")]
public class Shipper : IHasId<int>
{
[AutoIncrement]
[Alias("ShipperID")]
public int Id { get; set; }
[Required]
[Index(Unique = true)]
[StringLength(40)]
public string CompanyName { get; set; }
[StringLength(24)]
public string Phone { get; set; }
[References(typeof(ShipperType))]
public int ShipperTypeId { get; set; }
}
[Alias("ShipperTypes")]
public class ShipperType : IHasId<int>
{
[AutoIncrement]
[Alias("ShipperTypeID")]
public int Id { get; set; }
[Required]
[Index(Unique = true)]
[StringLength(40)]
public string Name { get; set; }
}
To do this you would need to use Raw SQL containing all the fields you want and create a new Model that matches the SQL, so for this example you would do something like:
public class ShipperDetail
{
public int ShipperId { get; set; }
public string CompanyName { get; set; }
public string Phone { get; set; }
public string ShipperTypeName { get; set; }
}
var rows = dbCmd.Select<ShipperDetail>(
#"SELECT ShipperId, CompanyName, Phone, ST.Name as ShipperTypeName
FROM Shippers S INNER JOIN ShipperTypes ST
ON S.ShipperTypeId = ST.ShipperTypeId");
Console.WriteLine(rows.Dump());
Which would output the following:
[
{
ShipperId: 2,
CompanyName: Planes R Us,
Phone: 555-PLANES,
ShipperTypeName: Planes
},
{
ShipperId: 3,
CompanyName: We do everything!,
Phone: 555-UNICORNS,
ShipperTypeName: Planes
},
{
ShipperId: 4,
CompanyName: Trains R Us,
Phone: 666-TRAINS,
ShipperTypeName: Trains
}
]

Resources