CRM 4 SERVERDEN TARİH OKUTMA VE FORMDA AJAX KULLANIMI

1-)Crm 4 de Formlara javascript yazıyoruz.Javascripte ise bilindiği gibi o anki saati Date() fonksiyonu  ile çekiyoruz.Ancak bilindiği gibi javascript client bazlı çalışır ve yüzden zamandan kontrol etmemiz gereken noktalarda serverın sistem saat,ne ihtiyaç duyarız

2-)Bunun için CRM formumuzda ActiveXObject den yararlanıyoruz ve

Oluşturduğumuz ActiveX nesnesini open metodu ile gideceği aspx sayfasını belirtiyoruz

Not:aspx sayfamızı inetpub da crmimiz altında bi yere publish ettikten sonra IIS den bu uygulamayı convert to application diyerek kullanıma hazır hale getirmemiz gerekiyor

Open Metodunda QueryString mantığıda kullanarak sayfamıza parametre gönderebiliyoruz

Yapmamız gereken tek şey formda adresten ?ParametreAdı=ParametreDeğeri şeklinde tanımlama yaparak kod tarafında ise Requst.QueryString[“Parametre”] adı ile yollanan değeri okutmaktır

var objHTTP = new ActiveXObject(“Msxml2.XMLHTTP”);

objHTTP.Open(“GET”, ‘/ISV/Bilgehan /ServerTimeControl/ServerTimeCheck.aspx’,false);

objHTTP.Send(null);

var response = objHTTP.ResponseText;

var currentdate =response.split(‘@’);

3-)Daha sonra sayfadan dönen kodu activeX objemize ResponseText diyerek alıyoruz.Tabi aspx formumuzda Response.Write ile istediğimiz değeride yazdırmamız gerekiyor

4-)Bizim senaryomuz gereği bir aspx sayfası oluturalım ve içine aşağıdaki gibi kodumuzu yazalım

namespace CRMTimeControllerAjax

{

public partial class ServerTimeCheck : System.Web.UI.Page

{

private string entity = string.Empty;

protected void Page_Load(object sender, EventArgs e)

{

Thread.CurrentThread.CurrentCulture = new CultureInfo(“en-US”);

string currentdate = DateTime.Now.ToString(“ddd MMM d HH:mm:ss UTCzzzzz yyyy”);

int  UTCPointIndex=   currentdate.LastIndexOf(‘+’)+3;//Benim istediğim formatta utcden sonra gelen + dan sonraki nokta yok

currentdate = currentdate.Remove(UTCPointIndex, 1);

Response.Write(currentdate+”@”);

}

}

}

5-) Burada response.writedan sonra direkt datetime.now diyerek bırakmadım nedeni ise CRMin tarih formatının biraz daha farklı olması

Crmde Date() fonksiyonu ile tarihi yazdırdığımız zaman verilen format benim serverım için UTC formatında ve bu tarih formatını kullanabilmek için kendi asp.net kodumda birkaç tane string işlemi yaptım ve en son olarak da bu formatta tarihi elde ederek en son response write @ işareti koyarak çıktımı yazdırdım.bunun nedeni ise

objHTTP.ResponseText; ile gelen değeri yazdırdığımızda çıktısını aşağıdaki formatta vermesi @ işareti koyarak split metodu ile ilk gelen tarih değerimizi alarak bir değişkene atıyoruz ve bu şekilde tarihimizi kullanıyoruz

var response = objHTTP.ResponseText;

var currentdate =response.split(‘@’);

6-)Son  Haliyle Serverdan sistem saatini kullanmak için aspx sayfamızda aşağıdaki kodlar(tabi siz kendi server formatınıza göre bu kodu düzenlemeniz lazım)

Thread.CurrentThread.CurrentCulture = new CultureInfo(“en-US”);

string currentdate = DateTime.Now.ToString(“ddd MMM d HH:mm:ss UTCzzzzz yyyy”);

int  UTCPointIndex=   currentdate.LastIndexOf(‘+’)+3;//Benim istediğim formatta utcden sonra gelen + dan sonraki nokta yok

currentdate = currentdate.Remove(UTCPointIndex, 1);

Response.Write(currentdate+”@”);

CRM Formdaki kodumuz ise aşağıdaki gibi olacaktır.

var objHTTP = new ActiveXObject(“Msxml2.XMLHTTP”);

objHTTP.Open(“GET”, ‘/ISV/Bilgehan/ServerTimeControl/ServerTimeCheck.aspx’,false);

objHTTP.Send(null);

var response = objHTTP.ResponseText;

var currentdate =response.split(‘@’);

var now =new Date(currentdate[0]);

CRM kategorisine gönderildi | Yorum bırakın

FORMDAN FORM TÜRETMEK VE GENERIC FORM MANTIĞI 2

Generic formlar yaparken designerın hata verdiğini ilk yazımda da belirtmiştim

Ancak haliyle bizim türettiğimiz formda da eklemeler vs yapabilmemiz için designerı

değiştirmemiz gerekiyor

Generic Formlarda designerı kullanmak için öncelikle bir ara form yaratıyoruz

Projemize birtane BaseTypeControl diye basetypeformdan türeyecek basit bir form atalım

public partial class BaseTypeControl : BaseTypeForm<BaseTypeEntity>

{

public BaseTypeControl()

{

InitializeComponent();

}

}

Formlarımızı kullanabilmemiz için BaseTypeForma artık Gerçek formlarımızdan direkt bağlantı olmayacak ve formlarımız BaseTypeControl formundan türeyecek şekilde ayarlayacağız.Ancak bunu yapmadan önce BaseTypeFormdaki kodlarımızda biraz değişiklik yapmamız gerekmektedir.

BaseTypeFormumuza öncelikle bir tane property ekliyoruz.Dikkat edileceği gibi bu property Tentity tipini alan ve virtual olarak tanımlanan bir property nedeni ise bunu diğer formlardan çağırırken override etmemiz gerekeceği için

public virtual Type CurrentEntityType

{

get

{

Type entityType = typeof(TEntity);

if (entityType == typeof(BaseTypeEntity)) return null;

return entityType;

}

}

Kodumuzda İse yukarıdaki yeri ekledikten sonra tek değiştirmemiz gereken yer typename direkt Tentity okuması yerine CurrentEntityTypeın adını alacak şekilde değiştirmemiz

string typename = CurrentEntityType.Name;

// string typename = typeof(TEntity).Name;

//BaseTypeFormun son hali

public partial class BaseTypeForm<TEntity> : Form where TEntity : BaseTypeEntity

{

public BaseTypeForm()

{

InitializeComponent();

}

public virtual Type CurrentEntityType

{

get

{

Type entityType = typeof(TEntity);

if (entityType == typeof(BaseTypeEntity)) return null;

return entityType;

}

}

private void BaseTypeForm_Load(object sender, EventArgs e)

{

FillGrid();

}

public void FillGrid()

{

SqlConnection conn=new SqlConnection(ConfigurationManager.ConnectionStrings["TelefonRehberiConnectionString"].ConnectionString);

string typename = CurrentEntityType.Name;

// string typename = typeof(TEntity).Name;

string sorgu = “Select * from “+typename;

SqlDataAdapter adap = new SqlDataAdapter(sorgu,conn);

DataTable dt = new DataTable();

adap.Fill(dt);

dataGridView1.DataSource = dt;

}

private void btnEkle_Click(object sender, EventArgs e)

{

SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["TelefonRehberiConnectionString"].ConnectionString);

string typename = CurrentEntityType.Name;

// string typename = typeof(TEntity).Name;

string sorgu = “insert into ” +typename + ” values(@Name)”;

SqlCommand cmd = new SqlCommand(sorgu, conn);

cmd.Parameters.Add(“@Name”, txtName.Text);

conn.Open();

cmd.ExecuteNonQuery();

conn.Close();

FillGrid();

}

public virtual void btnShowMessage_Click(object sender, EventArgs e)

{

MessageBox.Show(“BaseFormdur”);}}

BaseFormumuzda bunları yaptıktan sonra Projemize UserTypeForm2 diye yeni bir form ekliyoruz ve aşağıdaki şekilde kodlarını yazıyoruz.Görüldüğü gibi son eklediğimiz form artık BaseTypeControlden türeyen ve CurrentEntityType override ederek ilgili sınıfı gönderdiğimiz hale getirdik

public partial class UserTypeForm2 : BaseTypeControl

{

public UserTypeForm2()

{

InitializeComponent();

}

public override Type CurrentEntityType

{

get

{

return typeof(UserType);

}

}

}

İlk makaleyi yaptığınız formdan kalma ise bu değişiklikleri yapsanız bile designer hala hata veriyor olabilir.Bunun için ise yapmanız gereken projenizi kapattıktan sonra projenizin bin ve obj klasörlerini silip projeyi tekrar rebuild yapmanızdır.Ondan sonra formumuzu açtığımız zaman designerıda kullanabiliyoruz

.NET kategorisine gönderildi | Yorum bırakın

FORMDAN FORM TÜRETMEK VE GENERIC FORM MANTIĞIc-1

C# da kalıtım sadece sınıflarla sınırlı değildir.Formlar ve diğer kontrollerdede kalıtım mantığı uygulamak mümkündür

Genelde belli kalıplara göre yapılan projerelerde temel form tipleri belirleyerek oluşturulacak formların bunlardan miras alarak türetilmesi kod tekrarını önleyecektir

Tabi baseformlar tasarlamak için proje planını ve veritabanı tasarımını buna göre yapmakta fayda vardır

Örnek olarak Veri tabanında tip tablolarımızın olduğunu varsayalım.Tip tabloları genelde ID ve TipinAdı olacak şekilde veritabanınında tutulur ve genelde de başka alan almazlar

Veritabanımızda örnek olarak şu iki tablo olsun.Veritabanı tasarımımızı buna göre yapalım

Patterni bozmayacak şekilde bütün tip tablolarımızı veritabanında bu şekilde tasarlayacağız

PersonType–>ID,Name

UserType–>ID,Name

Daha sonra projemize BaseTypeForm ismiyle bir form ekliyoruz.Aşağıdaki gibi üstte ekleme alanı ve alttada bir grid olacak şekilde design ediyoruz.

Bir de projemize bir entity folder ekleyerek BaseTypeEntity diye bir sınıf ekliyoruz.Ayrıca BaseTypeEntity sınıfımızdan türeyecek PersonType ve UserType isimli iki sınıf daha ekliyoruz.

public class PersonType:BaseTypeEntity

{

}

Daha sonra BaseTypeFormumuza gelerek kod tarafında baktığımızda BaseTypeFormumuzun Formdan türediğini görüyoruz burayı

public partial class BaseTypeForm : Form

aşağıdaki gibi modifiye ediyoruz.Bu şu demektir.BaseTypeForm (BaseTypeForm<TEntiy>)

içine bir değer alır

alacağı bu değer ise BaseTypeEntity classından türeyecek bir sınıfdır.

(where TEntity : BaseTypeEntity)

public partial class BaseTypeForm<TEntity> : Form where TEntity : BaseTypeEntity

Yukarıdaki tanımlamayı yaptığımız anda formumuzun constructorı hata verecektir.Dikkat edeceğimiz gibi formlar partial şekilde tanımlanmıştır ve partialın anlamı bu classın başka bir yerde bir parçası daha olduğudur

Bu da windows formlar için tahmin edilebileceği gibi Forma ait Designer.cs dosyasıdır

Buraya gelip formun adının yanına BaseTypeForm<TEntity> şeklinde alacağı değeri ekliyoruz ve böylece constructorın verdiği hatada düzelecektir

Ve aşağıdaki gibi Gridi dolduracak ve veritabanımıza kayıt ekleyecek kodları yazalım.

Bu kodlarda standart Ado.Net kodları dışında bir kod bulunmamaktadır

Sadece string typename = typeof(TEntity).Name; şeklinde bir kod satırı vardır.Bu da bize runtime sınıfımıza gelecek olan sınıfın tipinin adını bulmaya yaracaktır

private void BaseTypeForm_Load(object sender, EventArgs e)

{

FillGrid();

}

public void FillGrid()

{

SqlConnection conn=new SqlConnection(ConfigurationManager.ConnectionStrings["TelefonRehberiConnectionString"].ConnectionString);

string typename = typeof(TEntity).Name;

string sorgu = “Select * from “+typename;

SqlDataAdapter adap = new SqlDataAdapter(sorgu,conn);

DataTable dt = new DataTable();

adap.Fill(dt);

dataGridView1.DataSource = dt;

}

private void btnEkle_Click(object sender, EventArgs e)

{

SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["TelefonRehberiConnectionString"].ConnectionString);

string typename = typeof(TEntity).Name;

string sorgu = “insert into ” + typename+ ” values(@Name)”;

SqlCommand cmd = new SqlCommand(sorgu, conn);

cmd.Parameters.Add(“@Name”, txtName.Text);

conn.Open();

cmd.ExecuteNonQuery();

conn.Close();

FillGrid();

}

Yukarıdaki kodları yazdıktan sonra projemize PersonTypeForm diye yeni bir form ekliyoruz

Görüldüğü gibi standart Formdan türeyen sade bir windows formu oluşturmuş olduk

Standart formdan türemesi yerine biz BaseType Formumuzdan türemesini istiyoruz

public partial class PersonTypeForm : BaseTypeForm<PersonType>

PersonTypeFormumuz BaseTypeFormdan türeyen ve içine PersonType sınıfımını alacak şekilde belirtceğimiz bir form haline geldi

Burada ise polimorfizm mantığından yararlandık nasıl mı şu şekilde BaseTypeForm içine BaseTypeEntity nesnesi istiyor.PersonType ise zaten BaseTypeEntity türediği için BaseTypeEntity gibi davranabiliyor.

PersonTypeFormumuzu çalıştırdığımız zaman BaseTypeFormumuza kodumuz dallandığında artık type namemizin PersonType olduğunu görüyoruz

Bu şekilde olunca PersonTypeFormumuza tek bir satır kod yazmadık sadece formun türeyeceği formu ve alacağı sınıfı belirttik

Benzer şekilde formumuza bir de UserTypeForm ekleyelim ve onada yukarıdaki benzer işlemleri yapalım

public partial class UserTypeForm : BaseTypeForm<UserType>

{

public UserTypeForm()

{

InitializeComponent();

}

}

Görüldüğü gibi birbirne benzer formlarımızı kod tekrarı yapmadan doğru veritabanı tasarımı ve kodlama mantığıyla seri bir şekilde oluşturduk

–Burada dikkat ettiğimiz iki nokta var Veritabanı tasarımı yaparken tüm tip alanlarını ID ve Name olacak şekilde tasarladım ve insert sorgusu standart hale geldi

–Runtime da bir nevi tablo adı olarak kullanmak üzere Nesneler tanımladım ve bunları Polimorfizm den yararlanabilmek için BaseTypeEntity türettim ve classların isimlerinin veritabanındaki tablolarla aynı olmasını sağladım.

Formdan form türetilirken base formda olan butonun vs click eventlerini veya fonksiyonlarını değiştirmek de isteyebiliriz.Bunun için BaseTypeForma bir button ekleyelim ve aşağıdaki gibi kodu yazalım

private void btnShowMessage_Click(object sender, EventArgs e)

{

MessageBox.Show(“BaseFormdur”);

}

Yukarıdaki gibi yazılırsa buttonun click eventine bir üst formda dokunulamayacaktır.Bunun için bu kodu şu şekle çevirelim

public virtual void btnShowMessage_Click(object sender, EventArgs e)

{

MessageBox.Show(“BaseFormdur”);

}

Burada private yerini public yaptım ve bir üst formda üstüne yazabilmek için fonksiyonu virtual olarak tanımladım

UserType formumuzda ise bu fonksiyonu override ederek değiştirebiliriz

public override void btnShowMessage_Click(object sender, EventArgs e)

{

MessageBox.Show(“UserFormdur”);

}

Uyarılar:

Base forma koyduğunuz kontrolleri silemezsiniz ve yerlerini değiştiremezsiniz

İkinci olarak da kalıtım alan formun designerı açılmayabilir.Bu çalıştırmada sorun vermez ancak designer hatalı kalır(Generic form mantığı kullandığımızda)

Bunun için yapılması gereken ise bir ara form kullanarak kalıtım yoluna gitmektir.Ancak yukarıdaki kodlara değişiklik yapılması gerekmektedir.Bunuda bir sonraki makalemde yapıyor olacağım…

.NET kategorisine gönderildi | Yorum bırakın

ASP.NET COOKIE KULLANIMI

Esasta cookienin en güzel kullanım yeri internet sitelerinin kullanıcı adı ve şifremi hatırla dediğimiz yerdir.Siteyi daha sonra kaydettiğimiz bilgisayardan açtığımızda kullanıcı adı ve şifremiz dolu gelecektir.Dolayısıyla bu bilgiler clientta cookielerde saklanır.Dolayısıyla istediğin yapıldığı bilgisayarda saklanır.

Cookie kullanımına ise diğer bir örnek hatırlatmalar olabilir.O gün client sisteme bağlandığında doğum günü ise bir popup mesaj çıksın ancak bu her sayfa load olduğunda değil bir seferlik çıksın ilk seferinde cookie değeri yazdırarak bu sayfanın bir seferlik açılmasını sağlayabiliriz

Şimdi Kullanıcı adı ve şifre kabul olduktan sonra eğer beni hatırla seçeneği seçili ise kullanıcıadı ve şifreyi bilgisayara kaydetmek istiyoruz.Bunun için aşağıdaki şekilde yeni bir cookie nesnesi oluşturup keyleri vererek buraya atama yapıyoruz

.Expires ile cookinin kaç gün saklanacağını belirtiyoruz

if (chbRememberme.Checked)

{

HttpCookie cook = new HttpCookie(“BenimLoginBilgilerim”);

cook["Username"] = txtUsername.Text;

cook["Password"]=txtPassword.Text;

cook.Expires=DateTime.Now.AddDays(1);

Response.Cookies.Add(cook);

}

Sayfamızı bidahaki açılışında kullanıcı adı ve şifremizin yazılı gelmesi için aşağıdaki kodu Sayfamızın loadına yazmamız yeterlidir

Request.Cookies["BenimLoginBilgilerim"]!=null bu kontrolle cookinin olup olmadığını kontrol ediyoruz

Request.Cookies["BenimLoginBilgilerim"]["Username"].ToString();Şeklinde ise oluşturduğumuz cookie içindeki bir keyi vererek değerini ulaşıyoruz

if (Request.Cookies["BenimLoginBilgilerim"]!=null)

{

txtUsername.Text = Request.Cookies["BenimLoginBilgilerim"]["Username"].ToString();

txtPassword.Text = Request.Cookies["BenimLoginBilgilerim"]["Password"].ToString();

}

Yukarıdakinden daha basit olarak aşağıdaki gibide cookie oluşturup değerini okutabiliriz

Response.Cookies["Username"].Value = “Bilgehan”; Tekli bir cookie oluşturuyoruz

Response.Cookies["Username"].Value = “Bilgehan”;

Response.Cookies["Username"].Expires = DateTime.Now.AddDays(5);

if (Request.Cookies["Username"] !=null)

{

txtUsername.Text = Request.Cookies["Username"].Value.ToString();

}

Yukarıdaki gibi okutabiliyoruz.

Cookielerle ilgili dikkat edilmesi gereken noktalar her clientın cookie ayarı açık olmayacağı için çalışmayabilir

Ayrıca diğer bir önemli nokta ise aynı isimli cookieye bi kere değer daha gönderilirse son gönderilen değer geçerli olacaktır

.NET kategorisine gönderildi | 1 yorum

C# REFLECTION KAVRAMINA BAKIŞ

C# da runtimeda tip bilgilerine erişebilmemize yarar.Kütüphane olarak System.Reflection namespace altındadır

Reflection ile runtimeda classın fieldların,propertilerin özelliklerine vs erişebilir ve ona göre işlemler yapabiliriz.ORM araçlarının temel mantığıda bunun üstüne kuruludur.

Örnek olarak veritabanımızdaki bir tablonun nesne olarak modellemesini yapalım

public class CustomerEntity

{

private int _CustomerID;

private string _Name;

private string _Surname;

private DateTime? _BirthDate;

[EntityPrimaryKey]

public int CustomerID

{

get

{

return _CustomerID;

}

}

public string Name

{

get

{

return _Name;

}

set

{

_Name = value;

}

}

public  string Surname

{

get

{

return _Surname;

}

set

{

_Surname = value;

}

}

public DateTime? BirthDate

{

get

{

return _BirthDate;

}

set

{

_BirthDate = value;

}

}

}

Görüldüğü gibi Veritabanımda CustomerID,Name,Surname,BirthDate olarak var olan 4 alanın kod tarafında nesne olarak modellemesini yaptım.Bunlardan CustomerID nin bir CustomAttribute ile primary Key olduğunu belirttim.Tablomun adıda Customer olsun.

Not:C# da Custom Attribute Tanımlama,yapmanız gereken sadece AttributeUsage Attribute kısmını sınıfın üstüne yazmak ve Sınıfınızın Attributedan türemesini sağlamaktır.Bu sayede artık biz de kendi kullanımımıza göre bir Attribute yaratmış olduk

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]

public class EntityPrimaryKey:Attribute

{

}

Benim senaryoma göre CustomerID de otomatik artan ve integer olsun

Formda butonun arkasına

CustomerEntity b = new CustomerEntity();

b.Name = “Bilgehan”;

b.Surname = “Yıldız”;

int a= EntityProcess<CustomerEntity>.Save(b);

yukarıdaki gibi kodumuzu yazalım.Ve EntityProcess sınıfımıza gelerek sınıfımızı oluşturalım.Ben yine ORM araçlarındaki gibi dinamik bir Save metodu yapmak istiyorum bunun için sınıfımı aşağıdaki gibi tanımlıyorum.Bu şekilde artık sınıfım generic olarak benim nesnelerimi alabilecek hale geliyor

public class EntityProcess<TEntity> where TEntity : class, new()

public static int Save(TEntity entity)

{

PropertyInfo[] properties = typeof(TEntity).GetProperties();

PropertyInfo ile Oluşturduğum Sınıfımın typeof(TEntity).GetProperties(); ile tüm propertylerini bir diziye alıyorum.Burada Tentity yerine üst katmandan çağırdığımızda CustomerEntity dolduruyor ve böylece dinamik olarak CustomerEntity classın içerisindeki propertylere ulaşabiliyoruz

foreach (PropertyInfo p in properties)

{

//Aşağıdaki komut ilede eğer gelen propertimin PrimaryKey Attribute varsa insert queryimize eklemiyoruz

if (p.GetCustomAttributes(typeof(EntityPrimaryKey), false).Count() <= 0)

{

//Get Value ilede metoda gönderdiğimiz nesnedeki propertylerin değerini okuyabiliyoruz.örnek CustomerEntity de Name propertsini Bilgehan olarak setlemiştik.Aşapıdaki kodla Bilgehan değerini okuruz

object columnValue = p.GetValue(entity, null);

if (columnValue != null)

{

Gene Reflection yardımı ile bulabileceğimiz şeylerden birede propertyimizin Int mi,String mi olduğu,nullable olup olmadığı gibi kavramlardır

Mesela BirthDate i nullable olarak tanımlamıştık.Bir kolon nullable ise hangi tipte olduğunu bulmak için önce birinci ifteki gibi GetGenericTypeDefinition() ile nullable olup olmadığını kontrol etmeliyiz.

Ondan sonra ise ikinci ifteki gibi p.PropertyType.GetGenericArguments()[0].Name ilede tipini kontrol edebiliyoruz.

if (p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))

{

if (p.PropertyType.GetGenericArguments()[0].Name == “Int32″)

{

return SqlDbType.Int;

}

Eğer propertyimiz nullable değilse aşağıdaki gibi kontroller yapabiliriz

PropertyType.Name demek yeterli oluyor

if (p.PropertyType.Name == “Int32″)

{

return SqlDbType.Int;

}

Son olarak genel olarak kodlarımıza göz atarsak TypeFinder benim yukarıda yazdığım şekilde propertnin Dbtype bulan bir sınıf.

public class EntityProcess<TEntity> where TEntity : class, new()

{

public static int Save(TEntity entity)

{

EMDbManager db = new EMDbManager();

PropertyInfo[] properties = typeof(TEntity).GetProperties();

string insertSql = “insert into {0} ({1}) values({2});select scope_identity()”;

StringBuilder columnNames = new StringBuilder();

StringBuilder parameterNames = new StringBuilder();

SqlCommand cmd = new SqlCommand();

foreach (PropertyInfo p in properties)

{

TypeFinder tp = new TypeFinder();

//Eger gelen entity bizim custom attribute ID içermiyorsa

//Otomatik Artan olmayan PrimaryKeyli yerlerde Custom PrimaryKey Attribute Olmayacak

if (p.GetCustomAttributes(typeof(EntityPrimaryKey), false).Count() <= 0)

{

object columnValue = p.GetValue(entity, null);

if (columnValue != null)

{

columnNames.Append(p.Name);

columnNames.Append(“,”);

parameterNames.Append(“@”);

parameterNames.Append(p.Name);

parameterNames.Append(“,”);

cmd.Parameters.Add(new SqlParameter(p.Name, columnValue, tp.FindType(p)));

}

}

}

insertSql = string.Format(insertSql, entity.GetType().Name.Replace(“Entity”, “”), columnNames.ToString().TrimEnd(‘,’), parameterNames.ToString().TrimEnd(‘,’));

//En son string Format ile benim sınıfımın adı CustomerEntity entity kısmını replace yok ediyorum ve generic olarak bir insert cümlesi yukarıdaki gibi oluşturmuş oluyorum.

.NET kategorisine gönderildi | Yorum bırakın

AYNI SERVERDA CRM 4 WORKFLOW VE PLUGIN DEBUG ETMEK

1-)Öncelikle iş akışı veya pluginimizin pdb dosyasını alıp default kurulu ise

C:\ProgramFiles\Microsoft Dyamics CRM\Server\bin\assembly klasörünün içine atıyoruz

2-)Daha sonra iisreset atıp Async Servisi restart ediyoruz

3-)Daha sonra crmmizi tekrar açıyoruz

4-)Son olarakda visual studiomuzdan Debugdan Attach to Process diyerek önce w3wp.exe i daha sonra da CrmASyncService attach ediyoruz(CrmAsynService attach edilirken ilk başta sorun verebilir attachi bir iki kere basmakta fayda var).Daha sonra trace etmek istediğimiz workflow veya plugini crmden çalıştırıp debug ediyoruz

CRM kategorisine gönderildi | Yorum bırakın

CRM 4 CUSTOM WORKFLOW KOD YAZIMI

1-)Öncelikle Microsoftun Sitesinden CrmSdk4 paketini indiriyoruz.

2-)Paketi kurduktan sonra Workflow template kullanabilmek için Sdk klasöründen visualstudiotemplates–cs–workflowactivity içindeki CrmWorkflowActivity.zip dosyasını alarak visual studiomuzun project templatelerinde c# klasörünün içine CRM diye bir klasör oluşturuyoruz.Ve Bu zip dosyamızı buraya extract ediyoruz.Böylece artık workflow için visual studiomuzda bir template olmuş oluyor.

My Documents\Visual Studio 2008\Templates\ProjectTemplates\Visual C#\CRM

3-)Ayrıca projemize aşağıdaki dll leride referans olarak vermemiz gerekiyor.(Bunlarda sdk klasöründe bin içinde mevcutlar)

Microsoft.Crm.Sdk;

Microsoft.Crm.SdkTypeProxy;

Artık workflowumuz kullanılmaya hazır hale geliyor

4-) DependencyProperty komutu Input veya Output Parametreler tanımlamak için kullanılır

[CrmInput("...")] Bu Attribute ilede property Crm de Workflow içinden ulaşmamızı sağlıyor

public static DependencyProperty CustomerCodeProperty = DependencyProperty.Register(“CustomerCode”, typeof(System.String), typeof(DeActiveRecordWorkflowActivity));

[CrmInput("CustomerCode")]

public String CustomerCode

{

get

{

return (String)base.GetValue(CustomerCodeProperty);

}

set

{

base.SetValue(CustomerCodeProperty, value);

}

}

5-) protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)

Bu fonksiyonu runtimede workflow tarafından çağrılarak işletilir.O yüzden işlemimizle ilgili business codeların işletildiği fonksiyon burasıdır.

6-)Crm 4 tarafından kullanılacak olan bütün Plug in assembly imzalanması gerekmektedir.Crm de workflow template kullandığınmız zaman zaten imza otomatik olarak gelmektedir.Ancak kendinizde imzalamak isterseniz

Projeye gelip,propertiesden–Signing den sign the assembly seçeneğini seçiyoruz.

7-)Yaptığımız Bu yeni workflowu Crm sistemimize tanıtmak içinde Plugin Registration Tool exeyi kullanıyoruz.

8-)Registerdan new assembly seçeneğini seçiyoruz.Dll Yerini load assemblyden yükleyerek,daha sonra onaylayarak crm sistemimize tanıtıyoruz.

9-)Crm asenkron servisi restart ettikten sonra artık workflowumuz crmde workflowlarda kullanılmaya hazır hale geliyor.

CRM kategorisine gönderildi | Yorum bırakın

CRM 4 ZORUNLU ALANLARI DOLDURMADAN KAYDI PASİF YAPMA VE WORKFLOW KULLANIMI

1-)Öncelikle crm de zorunlu alanlar doldurulmadan kayıt işlemleri tamamlanamaktadır.Aynı mantıkdan bir kaydı pasifleştirmek istediğimiz zamanda zorunlu alanları doldurmamız gerekir önce ancak zaten pasifleştirmek istediğimiz bir kayıt için bir daha alan doldurmak zaman kaybı olacaktır.(Özellikle sonradan eklenen zorunlu alanlar yeni kayıtlar için değilsede eski kayıtlar için sorun yaratacaktır)

Bu sıkıntıyı aşmak için önce şöyle bir yöntem denedim

Formun OnSave eventine

if(event.Mode==5) //formun etkinliğin kaldırılması olayıdır

crmForm.all.SetReqFieldLevel(“fieldname”,0);

bu kodda ancak zorunlu alanlar doldurulduktan sonra işleme geçmekte bu da bizim sorunumuzu çözmemektedir.

2-)Bu sorunu aşmak için yapmamız gereken ise isteğe bağlı çalışacak şekilde bir workflow oluşturmaktır.Aşağıdaki resimde ise iş akışını çalıştırmak istediğimiz varlığı seçiyoruz

3-) 2 olarak biz bunu sadece kaydı pasif yapmak istediğimiz zaman çalıştıracağımız için isteğe bağlı olarak işaretleriz ayrıca bütün kullanıcılarımızın kullanabilmesi içinde kapsamı organizasyon bazında seçiyoruz

4-)Daha sonra adım ekleden gelerek kaydın durum değerini etkin değil olarak vererek bir adım oluşturuyoruz.

5-)Burayı kaydedip kapattıktan sonra iş akışımızın etkin olabilmesi için yayında olması gerekir.Bunuda yayımla tıklayarak aktif ediyoruz.

Not:İş akışlarında değişiklik yapabilmek için tekrar taslak durumuna almanız gerekmektedir

6-)İş akışını yayınladıktan sonra iş akışını çalıştır öğesine tıklıyoruz

7-)Daha sonra oluşturduğumuz iş akışını seçip çalıştırıyoruz.Bi kaç dakika içinde kaydımız pasif hale geliyor.İlgili kaydı kapatıp tekrar açtığımızda artık bu kayıt pasif olmuş şekilde karşımıza geliyor.

CRM kategorisine gönderildi | Yorum bırakın

ENTITY FRAMEWORK – 1

1-)Entity Framework de,LLBLGEN,NHIBERNATE gibi bir ORM tooludur.Ancak Özelliği Microsoftun kendi orm toolu olduğu için Visual Studio 2008/2010 kurduğunuzda otomatik olarak gelmektedir.

İlk Önce Entity Frameworkdede nesneleri oluşturmamız gerekmektedir

2-)Bize ilk soracağı şey nesneleri databaseden modellemek istediğimiz,yoksa nesneleri kendimizin oluşturup sonradan mı database oluşturacağımıza karar vermemizdir.Empty model ise database vermeden kendimizin nesneleri oluşturması için kullanılır.Ancak daha sonra istersek tersine mühendislik yaparak databasemizi oluşturup connection bağlayabiliriz.Ancak bizim veritabanımız zaten mevcut olduğu için Generate from database seçeneğini seçiyoruz.

3-)Bir sonraki adımda Connectionımızı belirliyoruz

4-)Bu adımda modellemek istediğimiz database nesnelerimiz seçiyoruz.Tabi hepsini aynı ayda oluşturmak zorunda değiliz istersek bir kısım tablo ve viewleri oluşturmayabiliriz veya sonradan oluşturabiliriz

5-)Artık contextimiz oluşmuş durumdadır

6-)Contextimizi oluşturduktan sonra model browserdan Özelliklerimize bakabiliyoruz.

7-)Peki Veritabanımıza yeni bir tablo eklediğimiz zaman veya alan eklediğimizde bunları contexttimize nasıl yansıtırız.Örnek olarak Kisi Tablomuza yeni bir alan ekleyelim ve Kitap diyede yeni bir tablo ekleyelim.

Model Browserdan Model1.edmx in üstüne gelip sağ tuş dediğimizde

Update Model From Database diyoruz.Daha sonra açılan ekrandan veritabanımıza yeni eklenen tablo,view vs görüntüyebiliyoruz.Burada yeni eklenen kitap tablosunu seçiyorum.(Zaten mevcutta ekli tablolar üstünde değişiklikleri kendisi görüyor,ayrı birşey seçmeme gerek yok).Bu şekilde finishe bastığımızda artık yeni eklediğim TC kimlik numarası alanı ve yeni tablom benim modelimin içerisine gelmiş oldu.

8-)Lazy Load Kısaca verilerin bağlı oldukları verileride getirmesi işlemidir

Modelimiz(Contextimiz) in lazy load özelliğine bakmak istiyorsak isel Model Browserdan

Modelimizin Properties tıklayarak Lazy Load Enabled özelliğimizi True veya False

alabiliyoruz. Ben aşağıda lazy load açıkken ve kapalı iken Sql Profilerdan Sql giden sorguları trace ettim.

TelefonRehberiEntities tr = new TelefonRehberiEntities();

var kisi = tr.Kisi;

dataGridView1.DataSource = kisi;

Lazy Load Kapalı iken

Bu sorgu en temel sorgulardan biridir.

SELECT

[Extent1].[KisiID] AS [KisiID],

[Extent1].[Ad] AS [Ad],

[Extent1].[Soyad] AS [Soyad],

[Extent1].[Cinsiyet] AS [Cinsiyet],

[Extent1].[Yas] AS [Yas],

[Extent1].[TCKimlik] AS [TCKimlik]

FROM [dbo].[Kisi] AS [Extent1]

Lazy Load Açık iken

SELECT

[Extent1].[KisiID] AS [KisiID],

[Extent1].[Ad] AS [Ad],

[Extent1].[Soyad] AS [Soyad],

[Extent1].[Cinsiyet] AS [Cinsiyet],

[Extent1].[Yas] AS [Yas],

[Extent1].[TCKimlik] AS [TCKimlik]

FROM [dbo].[Kisi] AS [Extent1]

exec sp_executesql N’SELECT

[Extent1].[KisiID] AS [KisiID],

[Extent1].[DogumGünü] AS [DogumGünü],

[Extent1].[Meslek] AS [Meslek]

FROM [dbo].[KisiDetay] AS [Extent1]

WHERE [Extent1].[KisiID] = @EntityKeyValue1′,N’@EntityKeyValue1 int’,@EntityKeyValue1=1

Lazy load açıkken Görüldüğü gibi kayıtların ilişkili kayıtlarıda görmüş olur

.NET kategorisine gönderildi | Yorum bırakın

SSRS’DE BİR TABLO için ÇOKLU DATASET KULLANMA

Esasta pek çok okuduğunuz makalede bunun olanaksız olduğunu ve subreport kullanmanız gerektiği veya datasetleri birleştirmeniz gerektiğini okuyacaksınız

Ancak bunu yapmanın üçüncü bir yolu daha var subreport kullanmak(Tabi burda first(Fields!X.Value,’X dataset’) gibi bişeyden bahsetmiyorum çoklu kayıt taşıbilecek şekilde bir kullanımdan bahsediyorum.

Benim şöyle bir senaryom oldu.Ana bir raporum var ancak ben raporumda headerların başlıklarının gelen parametreye göre ingilizce veya Türkçe olmasını istiyorum.Ancak raporun bilgileri çektiği tabloların sorgusu ile verilen raporların başlıklarının tutulması sorgusu birbiriyle alakasız olacağı için farklı iki dataset kullanmam gerekiyor

Öncelikle aşağıdaki Kod bloğunu Raporumuzun custom code bölümüne ekliyoruz

Public  ColumnNamesList As String() = {}

Public  Function AddToColumnNamesList(txt as String) As string

dim L as integer = ColumnNamesList.Length

ReDim Preserve ColumnNamesList(L)

ColumnNamesList(L)=txt

return ColumnNamesList(L)

End Function

Public Function GetColumnName(i as integer) As string

return ColumnNamesList(i)

End Function

Yukarıdaki kod ne yapıyor

Birinci tablom ReportName diye bir DataSetten kolon başlıklarını okuyor

=Code.AddToColumnNamesList(Fields!displaytext.Value)

İkinci tablom ise Farklı bir datasetten kayıtlarımı okuyor

Ama ben aşağıdaki şekilde headerlarımın expressionına aşağıdaki kodu yazıyorum.Böylece verdiğim numaraya karşılık gelen Listeden başlığı okuyup ekranda gösteriyor

=Code.GetColumnName(4)

Ancak biz ilk kolon isimlerini taşıyan tablomuzun görünmesini istemiyoruz.Bunun için ssrs 2005 de tabloyu görünmez yapmamız yeterli ancak ssrs 2008 kullandığımızda bu işlem olmuyor maalesef

SSRS 2008 de ise bu mantığın çalışması için kolonun isimlerini taşıyan(ilk)tablonun hiddenın false olması gerekiyor.Böyle bir durumda ise tablonun width ve height 0 yapıyoruz ve Lokasyon olarakda ilk tablomuzdan yukarda olmayacak şekilde ikinci tabloyu yerleştiriyoruz.Eğer ikinci tablomuz birinciden daha yüksek olursa ikinci tablo birincide yazılanları algılamıyor ve hata veriyor(Saçma ama bu şekilde)

İyi Çalışmalar

SQL SERVER kategorisine gönderildi | Yorum bırakın