logo
Welcome Guest! To enable all features please Giriş or Kayıt.

Bildirim

Icon
Error

Ayarlar
Son mesaja git Go to first unread
bilgehanyildiz  
#1 Gönderildi : 19 Nisan 2015 Pazar 21:00:55(UTC)
bilgehanyildiz

Sıralama: Member

Gruplar: Registered
Katılan: 25.02.2015(UTC)
Mesajlar: 12
Turkey
Konum: İstanbul

2 Mesajına Toplam 2 Kere Teşekkür Edildi.
MONGODB .NET (C#) ENTEGRASYONU

Öncelikle C# entegrasyonu için kendiniz mongodb driverlarını kullanarak geliştirme yapabileceğiniz gibi mongorepository gibi open source kütüphanelerde mevcuttur.Codeplextten mongorepository ait dllleri indirerek bizim kendi örneğimizde yapacağımız pek çok işlemi yapabilirsiniz.


https://mongorepository.codeplex.com/SourceControl/latest

Ancak biz hem esneklik hem öğrenme amaçlı olarak bu makalede kendi sınıflarımızı yazacağız ama pek çok noktada mongorepository yazılmışı var cümlesini karşılamaktadır 

Öncelikle mongodb .net driverlarını projemize eklememiz gerekiyor

Bunun için birkaç yöntem kullanabiliriz

İlk olarak github tan gerekli dllleri indirebilirsiniz.(En son release dosyalarını indirmeye dikkat edin)


https://github.com/mongodb/mongo-csharp-driver/releases

Ya da mongo dbnin nuget desteğide mevcuttur

Install-Package mongocsharpdriver

Biz kendi örneğimiz için bir tane Windows application projesi açarak nuget yardımıyla güncel driverımızı indirelim


UserPostedImage

Nuget ile dlleri kendimizi aldıgımızda proje referanslarımızda mongodb dllerini görüyor olacağız.


UserPostedImage

Ancak yinede kendi mongo db kütüphanemizi yazarken githubta bulunan örnek repositorylerden faydalanıyor olacağız.

https://github.com/rsingh85/MongoDbRepository

Öncelikle bir tane base nesne classı oluşturalım,mongo dbye gidecek bütün nesnelerimiz entitybase türetiyor olacağız.Mongodb collectionda bulunan her bir documentin bir idsi vardır ve deserialize edilirken bu idde deserialize edilir.Bsonid attribute ile ilgili propertimizin bu dökümana ait identification alanı oldugunu belirttik


Kod:

namespace MongoDbSample.MongoRepository
{
    public  class EntityBase
    {
        [BsonId]
        public string Id { get; set; }
    } 
}




Not: Esasta bson attribute yerine direkt Objectid kullanabilirdik ancak json deserialize ederken bu şekilde kullanım size sorun çıkartıyor.Bu yüzden biz serialize işlemlerinde sorun yaşamamak için string bir alan tanımladık.ve bunu BsonId attribute ile işaretledik.

public ObjectId Id { get; set; }


İkinci olarak repository pattern yapısına uygun olarak bir tane repository interface hazırlayım.Bu interfacede temel crud işlemleri ve search ve getbyid gibi detay getiren fonksiyonlarımız olsun.


Kod:

namespace MongoDbSample.MongoRepository
{
    public interface IRepository<TEntity> where TEntity : EntityBase
    {
        WriteConcernResult Insert(TEntity entity);
        WriteConcernResult Update(TEntity entity);
        WriteConcernResult Delete(TEntity entity);
        IList<TEntity>
            SearchFor(Expression<Func<TEntity, bool>> predicate);
        IList<TEntity> GetAll();
        TEntity GetById(string id);
    } 
}


Bu interfacede değişik olarak dikkatinizi çeken nokta WriteConcernResult olmuştur.WriteConcernResult ile mongodbden işleminize ait dönüş bilgisini alabilirsiniz.
WriteConcernResultla mongodb de hata oluşmussa nedenini vs gibi bilgilerini elde edebilirsiniz


UserPostedImage

Şimdide bu interfaceden türeyecek kendi repositorymizi MongoDbRepository ismiyle oluşturalım

Kod:

using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Builders;
using MongoDB.Driver.Linq;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace MongoDbSample.MongoRepository
{
    public class MongoDbRepository<TEntity> :IRepository<TEntity> where TEntity : EntityBase
    {
        private MongoDatabase database;
        private MongoCollection<TEntity> collection;

        public MongoDbRepository()
        {
            GetDatabase();
            GetCollection();
        }

        public WriteConcernResult Insert(TEntity entity)
        {
            entity.Id = ObjectId.GenerateNewId().ToString();
            WriteConcernResult result = collection.Insert(entity);
            return result;
        }

        public WriteConcernResult Update(TEntity entity)
        {
            if (entity.Id == null)
                return Insert(entity);

           WriteConcernResult result=collection
                .Save(entity);
           return result;
                  
        }

        public WriteConcernResult Delete(TEntity entity)
        {
            WriteConcernResult result=collection
                .Remove(Query.EQ("_id", entity.Id));
            return result;
                    
        }

        public IList<TEntity>
            SearchFor(Expression<Func<TEntity, bool>> predicate)
        {
            return collection
                .AsQueryable<TEntity>()
                    .Where(predicate.Compile())
                        .ToList();
        }

        public IList<TEntity> GetAll()
        {
            return collection.FindAllAs<TEntity>().ToList();
        }

        public TEntity GetById(string id)
        {
            return collection.FindOneByIdAs<TEntity>(id);
        }

        #region Private Helper Methods
        private void GetDatabase()
        {
            var client = new MongoClient(GetConnectionString());

            var server = client.GetServer();

            database = server.GetDatabase(GetDatabaseName());
            }

        private string GetConnectionString()
        {
            return ConfigurationManager
                .AppSettings
                    .Get("MongoDbConnectionString")
                        .Replace("{DB_NAME}", GetDatabaseName());
        }

        private string GetDatabaseName()
        {
            return ConfigurationManager
                .AppSettings
                    .Get("MongoDbDatabaseName");
        }

        private void GetCollection()
        {
            collection = database
                .GetCollection<TEntity>(typeof(TEntity).Name);
        }
        #endregion
    } 
}



Repositorymizi yukarıdaki gibi yazdıktan sonra database bağlantı bilgilerimizi aşağıdaki gibi app.configimize ekleyelim

UserPostedImage

Şimdi bir kişi ve bu kişiye ait mailleri tutan model sınıflarımızı yazalım.Burda kilit nokta eklemek istediğimiz ana nesnenin EntityBaseden türeyerek bir bsonid yani mongodb id alanına sahip olmasıdır.

Kod:

namespace MongoDbSample.Model
{
    public class Person:EntityBase
    {
        public string Name { get; set; }

        public string Surname{get;set;}

        public List<Mail> Mails { get; set; }
    }
}

namespace MongoDbSample.Model
{
    public class Mail
    {
        public string MailAddress { get; set; }

        public bool IsBusiness{get;set;}
    }
}



Sınıflarımızı oluşturdak sonra ui projemize bir tane button ekleyip mongo dbye ilk kaydımızı ekleyelim

Kod:

private void btnInsert_Click(object sender, EventArgs e)
        {
            Person p = new Person();
            p.Name = "Bilgehan";
            p.Surname = "Yıldız";
            p.Mails = new List<Mail>()
            {
            new Mail(){ IsBusiness=true, MailAddress="abc@d.com"},
            new Mail(){ IsBusiness=false, MailAddress="e@f.com"},
            };

            MongoDbRepository<Person> Repository = new MongoDbRepository<Person>();
           WriteConcernResult result= Repository.Insert(p);
           if (!result.HasLastErrorMessage)
           {
               MessageBox.Show("Kayıt başarı ile eklendi");
           }
        }



UserPostedImage


Görüldüğü üzere oluşturdugumuz sınıfın adında ve sınıftaki propertylere göre veritabanımıza kayıt eklendi peki biz eğer veritabanındaki kolonlarla .net sınıfmızdaki alanların farklı olmasını istersek.

Temelde baktıgımızda mongodbye kayıt atmak ve kaydı okumak serialization işlemleri dolayısıyla burada nasıl ki datacontract serializerda propertylere alias vermek için [DataMember(Name="xxxxx ")] gibi yöntemler kullanıyorsak ise BsonElement kavramı devreye
devreye giriyor örneğimizi test etmek amaclı Mail sınıfında bulunan IsBusiness alanını IsBusinessMail yapalım ama geçmiş kayıtlarla uyumlu olması açısından database bu alanın eski adıyla IsBusiness olarak atılmasını istiyorum BsonElementin attributeın name özelliği burada devreye giriyor
Kod:

public class Mail
    {
        public string MailAddress { get; set; }
        [BsonElement("IsBusiness")] 
        public bool IsBusinessMail{get;set;}
    }


Şimdi Windows applicationdaki kayıt ekleme örneğimizdede alanın adını IsBusinesstan IsBusinessMaile çevirelim ve tekrar çalıştıralım.

Kod:

private void btnInsert_Click(object sender, EventArgs e)
        {
            Person p = new Person();
            p.Name = "Ümit";
            p.Surname = "Gündüz";
            p.Mails = new List<Mail>()
            {
            new Mail(){ IsBusinessMail=true, MailAddress="mybusinessmail@d.com"},
            new Mail(){ IsBusinessMail=false, MailAddress="mypersonelmail@f.com"},
            };

            MongoDbRepository<Person> Repository = new MongoDbRepository<Person>();
           WriteConcernResult result= Repository.Insert(p);
           if (!result.HasLastErrorMessage)
           {
               MessageBox.Show("Kayıt başarı ile eklendi");
           }
        }



UserPostedImage

Görüldüğü üzere propertyimize bir nevi alias vermiş olduk.Bu şekilde serializable işlemlerinde size yardımcı olabilecek farklı attributelarda mevcuttur.

UserPostedImage

Örnek olarak .net classınıza koydugunuz ancak database kaydının atılması istediğiniz alan varsa BsonIgnore attribute kullanabilirsiniz tıpkı xml serialization işlemlerinde kullandınız XmlIgnore attribute gibi

UserPostedImage

Veritabanında hangi alana collectiona kayıt atacağımız ise repositorydeki getcollection metodundan kalıyor bizim mantıgımızda classın adı collectionın adına eşit oluyor ancak isterseniz custom attributelar yapıp bu metodu değiştirerek istediğiniz collection adına göre kayıt işlemi yapmanızda mümkün.

Mesela mongorepository kütüphanesinde CollectionName diye bir attribute yaratıp bu attribute varsa collection adını buradan al yoksa sınıf adından al gibi bir yöntem geliştirmişler ,kendi mongo kütüphanenizi yazacaksanız bile mongorepository open source açıp kodlarına bakmak faydalı olabilir.


Kod:

[AttributeUsage(AttributeTargets.Class, Inherited = true)]
    public class CollectionName : Attribute
    {

  private static string GetCollectioNameFromInterface<T>()
        {
            string collectionname;

            // Check to see if the object (inherited from Entity) has a CollectionName attribute
            var att = Attribute.GetCustomAttribute(typeof(T), typeof(CollectionName));
            if (att != null)
            {
                // It does! Return the value specified by the CollectionName attribute
                collectionname = ((CollectionName)att).Name;
            }
            else
            {
                collectionname = typeof(T).Name;
            }

            return collectionname;
        }




Diğer metodlarımızada kısaca göz atalım
Örnek search metodumuz linq sorgusu yazar gibi kullanabiliyoruz

Kod:

private void btnSearch_Click(object sender, EventArgs e)
        {

            MongoDbRepository<Person> Repository = new MongoDbRepository<Person>();

           var Searchlist =  Repository.SearchFor(p=>p.Name.Contains("Bilgehan"));
        }




UserPostedImage

Örnek olarak mongodbde bir kayıt güncelleme kaydın son halini çekip yeni bir mail ekleme örneği yapalım

Kod:

private void btnUpdate_Click(object sender, EventArgs e)
        {
            MongoDbRepository<Person> Repository = new MongoDbRepository<Person>();
          Person p=  Repository.GetById("553365800529210aa0a24054");
          p.Mails.Add(new Mail() { IsBusinessMail = false, MailAddress = "extraaddedmail@f.com" });
          WriteConcernResult result = Repository.Update(p);
          if (!result.HasLastErrorMessage)
          {
              MessageBox.Show("Kayıt başarı ile güncellendi");
          }
        }



UserPostedImage

Bu şekilde de bu yazımızda mongodb c# entegrasyonun temel halini görmüş olduk.


Bu konudaki kullanıcılar
Guest
Forumu Atla  
Bu foruma yeni konular postalayamazsınız.
Bu forumda ki konulara yeni posta gönderemezsiniz.
Bu forumdaki postalarınızı silemezsiniz.
Bu forumdaki postalarınızı düzenleyemezsiniz.
Bu forumda anketler yaratamazsınız.
Bu forumdaki anketlere oy veremezsiniz.