1. Cum obtineti Connection String curat din Entity Framework Connection String
Sa zicem ca aveti definit connection string pentru EF in (web|app).config , ceva de genul :
<connectionStrings>
<add name="iERPEntities" connectionString="metadata=res://*/ERP.csdl|res://*/ERP.ssdl|res://*/ERP.msl;provider=System.Data.SqlClient;provider connection string="Data Source=PC;Initial Catalog=ERP;Persist Security Info=True;User ID=x;Password=xy;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" />
Si vreti sa preluati rezultatele de la o procedura stocata sau doar sa o executati, fara sa va mai chinuiti sa o treceti prin EF (mai mare deranjul). In consecinta va trebuie connection string-ul.
2. Cum faci Union – sau Join - intre 2 IQueryable – ca sa iti dea macar una din ele, daca cealalta e null ?
3. Daca stii cheia unui obiect -de obicei long ID – cum obtii obiectul ?
4. Cum poti vedea ce genereaza, ca string sql, entitycontext – fara sa stai cu profiler-ul pe Sql Server ?
5. Daca vreti sa faceti o tabela pentru ca sa accesati/modificati continutul cu EF, ce este BestPractices de definit la ea ?
6. Cum validati un obiect in EF inainte de a salva ?
Va las sa va bateti capul! Raspunsurile mai jos…
Rezolvarea 1.
string sqlc = "";
using (ERPEntities e = new ERPEntities("name=iERPEntities"))
{
EntityConnection ec = e.Connection as EntityConnection;
sqlc = ec.StoreConnection.ConnectionString;
}
De ce e.Connection nu e direct EntityConnection si trebuie cast-uit, depaseste imaginatia mea …
Rezolvarea 2.
public static IQueryable<T> coalesceIntersect<T>(IQueryable<T> x, IQueryable<T> y)
where T : class
{
if (x == null)
return y;
if (y == null)
return x;
return Queryable.Intersect<T>(x, y);
}
Rezolvarea 3.
/// <summary>
/// see also http://msdn.microsoft.com/en-us/library/bb896251.aspx
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="o"></param>
/// <param name="ID"></param>
/// <param name="Include"></param>
/// <returns></returns>
public static T FindFromPrimaryKey<T>(this ObjectQuery<T> o, long ID, params string[] Include)
where T : EntityObject
{
Type t = typeof(T);
string FullPath = t.FullName;
if (!KeysForObject.ContainsKey(FullPath))
{
lock (KeysForObject)
{
if (!KeysForObject.ContainsKey(FullPath))
{
foreach(PropertyInfo pi in t.GetProperties())
{
object[] attr = pi.GetCustomAttributes(typeof(EdmScalarPropertyAttribute),false);
if(attr != null && attr.Length ==1)
{
EdmScalarPropertyAttribute a=attr[0] as EdmScalarPropertyAttribute;
if(a.EntityKeyProperty)
{
KeysForObject.Add(FullPath,pi.Name);
break;
}
}
}
}
}
}
if(Include != null && Include.Length > 0)
{
foreach(string s in Include)
{
o=o.Include(s);
}
}
return o.Where("it." + KeysForObject[FullPath] + " = " + ID).FirstOrDefault();
Rezolvarea 4.
http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=1555711&SiteID=1
Rezolvarea 5.
Definiti neaparat Primary Key ( eu de obicei pun un bigint identity )
Rezolvarea 6.
Vedeti http://msdn.microsoft.com/en-us/library/cc716714.aspx
Adaugati o clasa partiala de tipul entitatii in care puneti partial pe OnContextCreated ca sa interceptati SavingChanges
partial class Entities
{
partial void OnContextCreated()
{
this.SavingChanges += new EventHandler(Entities_SavingChanges);
}
}
Eu am facut apoi o interfata IValidate de felul urmator – simplist – :
public enum ISValid
{
Yes,
No,
SendDataContext
}
public interface IValidate
{
ISValid IsValidForSaving(ObjectStateEntry ose, out string mesaj);
}
public interface IValidateDataContext // daca am nevoie de verificari mai ample cu alt obiect …
{
bool IsValidForSavingDataContext(ObjectContext oc, ObjectStateEntry ose, out string mesaj);
}
Apoi pe SavingChanges :
void Entities_SavingChanges(object sender, EventArgs e)
{
Entities context = sender as Entities;
foreach (ObjectStateEntry ose in context.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified))
{
if (ose.Entity == null)
continue;
IValidate iv = ose.Entity as IValidate;
if (iv != null)
{
string mesaj;
switch (iv.IsValidForSaving(ose, out mesaj))
{
case ISValid.No:
throw new NotValidException(ose.Entity.GetType().Name, mesaj);
case ISValid.Yes:
break;
case ISValid.SendDataContext:
IValidateDataContext ivDC = ose.Entity as IValidateDataContext;
if(!ivDC.IsValidForSavingDataContext(context,ose, out mesaj))
throw new NotValidException(ose.Entity.GetType().Name, mesaj);
break;
}
}
Ok, se putea si mai bine, cu IDataErrorInfo – dar … sa o lasam asa deocamdata