Using Linq with existing Objects - c#

My system has this pattern DAO->Objects->facade->View
so i have a DAO to query database, and instantiate objects, this objects has only attributes (just a container / entity), i want to use LINQ in DAO part, but i dont realize how to pass my objects becouse LINQ generate 1-per table.
namespace ykpObjects.Objects
{
public class Customer
{
public string name { get; set; }
public Cidade()
{
cidadeID = 0;
}
}
}
namespace ykpData.Components.MSSQL
{
public class CustomerDC : DataComponentCM, ICustomerDC
{
Customer ICustomerDC.RecuperaPorID(int CustomerID)
{
Customer Customer = new Customer();
using (MDDataContext omd = new MDDataContext(base.PreencherConexao()))
{
sp_mkp_Customer_SelectByIDResult result = omd.sp_mkp_Customer_SelectByID(CustomerID).SingleOrDefault();
if (result == null)
return null;
Customer.name = result.name;
return Customer;
}
}
}
}
I use DAO to call sprocs, so i get sproc results and instanciate a object of Customer for exemple, and pass this to control, now i want to change to linq but i dont wanna change all object structure to minimalize the impact.
Any advice ?

I'm not exactly sure what you are talking about with your current setup, but I think you're asking how to re-use the objects you currently have with Linq to SQL, rather than generating new ones from a dbml file. Am I right?
If so, you have a few options. You can use attributes to decorate your existing objects so that you can populate them with L2S, or you can create mapping files.
Some info here: http://www.sidarok.com/web/blog/content/2008/10/14/achieving-poco-s-in-linq-to-sql.html
I use Linq to SQL with attributes to achieve a "code first" solution, here's an example class:
[Table(Name = "Countries")]
public class Country
{
[Column(IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
public int CountryId { get; set; }
[Column]
public string iso2 { get; set; }
[Column]
public string iso3 { get; set; }
[Column]
public string name_en { get; set; }
}
To work with this object:
var context = new DataContext(ConnectionString);
var data = context.GetTable<Country>().Where(c => c.CountryId == 1);

Related

Reading data from DB using Entity Framework results in missing fields of an object

I currently have 2 models. One model references the other model. I am able to write the data perfectly well to the db. however when I read the data I get an incomplete object. One of the fields of that object is missing. This is what my models look like
public class Student
{
public int Id { get; set; }
public List<Sport> Sports { get; set; }
public string StudentName { get; set; }
}
public class Sport
{
public int Id { get; set; }
public string SportName { get; set; }
}
public class DbContext : DbContext
{
public DbContext()
: base("name=StudentContext")
{
}
public DbSet<Student> Students { get; set; }
}
Now I am writing the Student object like this
//Writing to the DB
Student stud = new Student()
{
StudentName = "Andrew",
};
stud.Sports = sportList; //Contains a sport List
this.context.Students.Add(device);
this.context.SaveChanges();
After writing the object to the DB I noticed that both the tables got populated and it looks good. However when I attempt to read the object back like this
The Sport List in Student does not get populated and comes back as NULL
//Reading from DB - Sports field missing
var a = this.context.Students.FirstOrDefault();
List<Sport> actions = a.Sports; //Returns null Why ??
Any suggestions on what I might be doing wrong ? How can I get the sports field as well ?
change in edmx file
<EntityContainer Name="StudentContext" annotation:LazyLoadingEnabled="false">
OR
{
public DbContext()
: base("name=StudentContext")
{
this.Configuration.LazyLoadingEnabled = false;
this.Configuration.ProxyCreationEnabled = false;
}
public DbSet<Student> Students { get; set; }
}
Or you can also modify your query
var a = this.context.Students.Include(s => s.Sports).FirstOrDefault();
Actually you do NOT need to do this (and you should not because in this way all the navigation properties inside the current DbContext will be eager loaded):
this.Configuration.LazyLoadingEnabled = false;
According to the reference you have already disabled lazy loading for the navigation property Sports by declaring it as a non-virtual property.
Loading of the Sports collection can still be achieved using eager loading or the Load method.
(Adapted to this case from the doc)

C# map two complex objects

I have four classes :
public class Customer
{
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Product> Product { get; set; }
}
public class Product
{
public int ProductNumber { get; set; }
public string ProductColor { get; set; }
}
///////////////////////////////////////////////
public class Customer_
{
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Article> Article { get; set; }
}
public class Article
{
public int ArticleNumber { get; set; }
public string ArticleColor { get; set; }
}
And one instance :
var Cus = new List<Customer>
{
new Customer()
{
FirstName = "FirstName1",
LastName = "LastName1",
Product = new List<Product>
{
new Product()
{
ProductColor = "ProductColor1",
ProductNumber = 11
}
}
},
new Customer()
{
FirstName = "FirstName2",
LastName = "LastName2",
Product = new List<Product>
{
new Product()
{
ProductColor = "ProductColor2",
ProductNumber = 12
}
}
}
};
I want to create a new object List<Customer_> with the value of my instance Cus. For example Customer.FirstName = Customer_.FirstName, Customer.Product.ProductColor = Customer_.Article.ArticleColor etc
What is the best way to do this easily, could one use a Dictionary?
Mapping can be accomplished through the use of an Interface.
Define an interface(s) which provide a mapping of logically named properties such as the common color properties you mention:
// Some entities have different named properties but can be joined
// using those properties. This interface shows a common color which
// when implemented will route the processing to a common shared property
// which reports and sets the associated color.
public interface IDefinedColor
{
string Color { get; set; }
}
If you have to create partial classes for Product and Article and have them adhere to said interfaces. Hint if using an entity mapper such as EF this is a great way to do such maping using partials. Implement implement the interface and hook up the commonality:
// Holds the common properties for future processing.
public partial class Product : IDefinedColor
{
public string Color
{
get { return ProductColor; }
set { ProductColor = value; }
}
}
Then work off of the IDefinedColor mapped implementations as needed.
By using interfaces one is letting all future developers know of the contract which specifies a business logic equality in the properties and it is not hidden in other joining classes.
You could create a mapper extension class
public static class MapperExtension
{
public Customer_ Convert(this Customer customer)
{
return new Customer_()
{
FirstName = customer.FirstName,
LastName = customer.LastName,
Article = customer.Product.Convert()
};
}
public static List<Article> Convert(this List<Product> products)
{
return products.Select(x=> new Article(){
ArticleNumber = x.ProductNumber,
ArticleColor = x.ProductColor
};
}
}
make sure you reference the proper namespace where you place the extension class.
Call the code like this
Where customers is a List filled from your code
List<Customer_> convertedCustomers_ = customers.Select(x=> x.Convert()).ToList();
It depends on the relationhip between those components but I would simply add constructor to Customer_ that accepts a Customer object. And then you invoke that do perform the conversion. e.g.
public class Article
{
public Article(Product source)
{
this.ArticleNumber = source.ProductNumber;
this.ArticleColor = source.ProductColor;
}
}
public class Customer_
{
public Customer_(Customer source)
{
this.FirstName = source.FirstName;
this.LastName = source.LastName;
this.Article = source.Product.Select(o => new Article(o)).ToList()
}
...
}
//and finally to convert the list you can do something like
//initial list
var Cus = new List<Customer>() { ... etc. }
/converted list
var Cus_ = Cus.Select(o => new Cusomter_(o)).ToList();
Edit: I see from your comment above that you actually have 100 properties to map. I can see this is a pain. But if you have complex transformations like Product to Article then I would still go the manual route as above so you can be completely clear about what is going on. Alternatively you could look to use inheritance to redesign your objects with common base classes or interfaces, that would probably make mapping easier.

ViewModel Object Convert to Entity Framework Object

Goal: to save ViewModel object by Entity Framework. I have UserViewModel object which has list of UnitViewModel. Then, I have a UserAdapter class which converts UserViewModel into Entity Framework User object (see Convert()below how).
Now, my question is how do I convert this list of UnitViewModel to its corresponding Entity Framework Unit list? - Do I have to get each object from DB Context by calling something like context.Units.Where(u=>myListofUnitIDs.Contains(u.UnitID))?
public class UserViewModel
{
public Guid? UserID { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Password { get; set; }
public DateTime? CreateTime { get; set; }
public List<UnitViewModel> UserUnits { get; set; }
}
public class UnitViewModel
{
public Guid UnitID { get; set; }
public string Name { get; set; }
public int? SortIndex { get; set; }
public DateTime CreateTime { get; set; }
public bool Assigned { get; set; }
}
public class UserAdapter
{
public static User Convert(UserViewModel userView)
{
User user;
if (userView.UserID.HasValue)
{
using (var provider = new CoinsDB.UsersProvider())
{
user = provider.GetUser(userView.UserID.Value);
}
}
else
{
user = new User();
}
user.FirstName = userView.FirstName;
user.LastName = user.LastName;
user.Password = StringHelper.GetSHA1(userView.Password);
user.UserName = user.UserName;
user.CreateTime = DateTime.Now;
// Problem here :)
// user.Units = userView.UserUnits;
return user;
}
}
UPDATE: The main concern here is that I have to retrieve each Unit from database to match (or map) it with ViewModel.Unit objects, right? Can I avoid it?
For your information, this operation is called as Mapping mainly. So, you want to map your view model object to the entity object.
For this, you can either use already existed 3rd party library as AutoMapper. It will map properties by reflection which have same name. Also you can add your custom logic with After method. But, this approach has some advantages and disadvantages. Being aware of these disadvantages could help you to decide whether you must use this API or not. So, I suggest you to read some articles about advantages and disadvantages of AutoMapper especially for converting entities to other models. One of such disadvantages is that it can be problem to change the name of one property in the view model in the future, and AutoMapper will not handle this anymore and you won't get any warning about this.
foreach(var item in userView.UserUnits)
{
// get the mapped instance of UnitViewModel as Unit
var userUnit = Mapper.Map<UnitViewModel, UserUnit>(item);
user.Units.Add(userUnit);
}
So, I recommend to write your custom mappers.
For example, I have created a custom library for this and it maps objects lik this:
user.Units = userView.UserUnits
.Select(userUnitViewModel => userUnitViewModel.MapTo<UserUnit>())
.ToList();
And I am implementing these mapping functions as:
public class UserUnitMapper:
IMapToNew<UnitViewModel, UserUnit>
{
public UnitViewModel Map(UserUnit source)
{
return new UnitViewModel
{
Name = source.Name,
...
};
}
}
And then in runtime, I am detecting the types of the objects which will be used during mapping, and then call the Map method. In this way, your mappers will be seperated from your action methods. But, if you want it urgently, of course you can use this:
foreach(var item in userView.UserUnits)
{
// get the mapped instance of UnitViewModel as Unit
var userUnit= new UserUnit()
{
Name = item.Name,
...
};
user.Units.Add(userUnit);
}

most efficient way to populate composite class

I just want to get some opinions on the most efficient and quickest way to populate my composite class using the EF4.0. I have a parent class which has a structure similar to the class below. It mirrors my database structure.
public class Person
{
public string FirstName { get; set; }
........
public Address WorkAddress { get; set; }
public IList<Account> Workspace { get; set; }
}
public class Address
{
public string FirstName { get; set; }
......
}
public class Account
{
public string SortCode { get; set; }
public IList<string> TransactionHistory {get; set;}
......
}
So, at this moment in time I pull back all the 'Persons' from the EF and I loop through each of them and populate the Address and Accounts for each. Lazy loading is enabled, so I have to encapsulate all my loops in the using statement or my Accounts will be empty when I try to iterator through them. So, can I disable lazy loading for this call only or should approach the population of my list of persons in another manner.
using (var entities = new PersonEntities())
{
var dbPeople = (from person in entities.Persons
select person).ToList();
foreach(var person in dbPeople)
{
foreach(var account in person.Accounts)
{
// In here I populate my 'Person' business object account and add it to my collection to return.
}
}
}
If I got you right, you're going to include the relation keeping the LazyLoading enabled. You can do this for the query using the Include method:
using (var entities = new PersonEntities())
{
var dbPeople = entities.Persons.Include("Accounts").ToList();
foreach(var person in dbPeople)
{
//Do nothing with Accounts if the relation is mapped correct
}
}
EDIT:
Also you can disable LazyLoading for the created PersonEntities instance's lifetime:
using (var entities = new PersonEntities())
{
entities.Configuration.LazyLoadingEnabled = false;
//...
}

Entities to DTO - Entity framework

Please review my code. For every my Entity i've created a service class, where i put all the access methods for this entity.This method are doing the transformation from the Entities to my DTO classes. This methods are called from the Web layer or a bussines method. Am I doing this righth? Or should I do it differently ?
The service method:
public static IEnumerable<OsobaDto> GetNakupyByOsoba(Guid guid)
{
using (FinanceEntities finance = new FinanceEntities())
{
var osoby = from o in finance.OsobaSet
where o.Nakupy.Any(n => n.idnakupu == guid)
select new OsobaDto
{
Id = o.idosoba,
Meno = o.meno,
Priezvisko = o.priezvisko,
Prijem = o.prijem,
Nakupy = o.Nakupy.Select(n => new NakupDto
{
IdNakupu = n.idnakupu,
Cena = n.cena,
Datum = n.datum
})
};
return osoby;
}
}
And the DTO class
public class NakupDto
{
public Guid? IdNakupu
{
get;
set;
}
public Decimal Cena
{
get;
set;
}
public DateTime Datum
{
get;
set;
}
public IEnumerable<OsobaDto> Osoby
{
get;
set;
}
public OsobaDto Platil
{
get;
set;
}
Everything is good, but I have one suggestion. If you have a lot of DTO objects you shoud think about writing a general converter. It can be done using reflection and explicit conversion operators.
Keep in mind the query wont actually hit the database until you actually use the IEnumerable you are are returning (because of deferred execution). I'm not sure how that will work since you are disposing the FinanceEntities before you actually execute the query. Assuming that works, it looks fine to me.

Categories