Konu: .NET ve VFP Karşılaştırması.
Öncelikle tüm Fox4um 'a merhabalar.
Şimbi benim dediğim gibi: "VFP ile .NET in nesini karşılaştırıcaz? Ne gerek var? Biz zaten topyekün Foxpro 'cuyuz" dimi?
Daha iki gün öncesine kadar; yukarıdaki cümlenin aynısını hatta daha da fazlasını benden duyardınız? Tamam VFP yi kendi çapımda biliyorum; .NET 'i de. Bu arada; "biliyorum" demediğime lütfen dikkat edin! ( Kendi çapımda biliyorum. ).
Hep VFP nin hızını övüp duruyoruz. Hızlı uygulama geliştirme; verileri hızlı işleme; Veri tabanı ( yada yenilerin tabiriyle Table ) işlemeye yönelik düzinelerce komut, object oriented modelleme (C# ile kesinlikle kıyas bile götürmez. Çok çok gerilerde ama yinede bir veritabanı programcısının işini fazla fazla görecek kadar iyi.), Win API ve ActiveX kullanımı, Office entegrasyonu. vs. v.s...
Şimdi bunbları neden mi yazıyorum. Biraz sabır Gülümsediğime bakmayın, bu gülümseme biraz sinirdenkendime hayıflanmamdan. !!!
Geçen gün can sıkıntısı ile Çetin Üstad' a bir bulaşıyim dedim. Bulaşmak derken bir konuda biraz görüş almaktan; vakti varsa da bir kaç kelime sohbet etmek niyetindeydim. Sen misin bulaşan!!! :
-Üstad, biraz boş vaktin var mı?
- Evet olabilir?
- Bir şey sorucaktım da?
- ?. ( Sor işte be adam ne bekliyorsun!! - Uğur 'un notu. )
- ..... konusunda ne düşünüyorsun biraz yardıma ihtiyacım var. ( Konu tabii ki VFP )
Ve arkadaşlar; ben şu anda bu soruyu sorduğuma öyle pişmanım ki. Bana kibarca verilen cevabı aynen aktarıyorum.
- Akşama biraz boş zamanın var mı? Teamviewer ile bağlanıp sana biraz bir şeyler göstereyim. Bence artık sorduğun türdeki işleri C# ile yapmalısın.
- İyi de Üstad C# için 40 fırın ekmek yemek lazım.
- Yok yok hiçde öyle diil, akşama sana 10 dk bir şeyler göstereyimde ne kadar kolay olduğunu gör.
- ( DUMUR ! Vay be. Ne kadar da güzel 10 dk da C# programcısı olucakmışım. Yaşasınn!! Ya ba daba duuu. ).
İyi de Üstad, ben 2 kış dönemi o .NET ve C# 'ın kursuna gittim. Hiç de öyle dediğin gibi görünmüyordu meret.
- Yok ya gözünde büyüttüğün kadar diil. Şimdi işim var. Gece 10 da görüşürüz.
( İşim var işte! Daha tutma beniii. Daha forumlarda cevap bekleyen bilmem kaç düzine soru var. Onlara sihirli değnekle dokunmam lazım. Milletinde işi gücü yok sorup duruyor. Böylede olmaz ki canım. Şimdi biri sordumu cevap vermemek te olmaz dimi. Bu sihirli değneği boşuna tutmuyoruz elimizde. Hem yeni çıkan hangi teknolojiler var, kimsenin bilmediği yada aklına gelmemiş ne keşifler yapmak lazım. Ohooo Çoook işim var çok. Tutma beni Uğur. TUTMAAA - Uğur 'un hayal gücü -)
-Tamam Üstad, gece görüşürüz.
Ve gece 10 suları ....
Teamviewer ile hızlı bir bağlantı ve show başlıyor...
Şimdi heyecanla şov içeriğini merak eden arkadaşlara sadece önsöz vericem. Gerisi hep beraber Çetin Üstad 'ı ikna edip eski günlerdeki gibi Go2meeting görüşmesine kalıyor. Tabi ikna olursa
Ben artık VFP 'nin kolay ve hızlı kullanımı konusunda kesinlikle bir karşıt gruptayım. Yok artık öyle bir şey. Foxpro gerçekten bitmiş, üstelik okeye dönüyor. Hemde Çiftten okey.. Neden mi? Devam ediyorum... :
Çalışmaortamı: Windows 7 RC2 + Visual Studio 2010 ( .Net 4.0 ) + SQL Server 2008 Express Edt. + Linq Pad + AdvantureWorks (SQL Server 2008) + Northwind(SQL Server 2000)
Sözün kısası Konuyu biraz .NET ve Linq ya bırakalım.
---------------------------------------------------------
// LinqPAD örneği:
DirectoryInfo di = new DirectoryInfo(@"C:\Program Files\Microsoft Visual FoxPro 9");
string[] extensions = {".scx",".prg"};
var result =
from f in di.GetFiles("*.*",SearchOption.AllDirectories)
where extensions.Contains( f.Extension.ToLower() )
select new {f.FullName, f.CreationTime, f.Attributes, f.Length};
result.Dump("File System Query");
// RUN i
Ve karşınızda dosya listesi... Kod kısa, gayet okunaklı ve hepsinden öte, Intellisense inanılmaz iyi.
şimdi benzer işi yapan bir VFP kodu, tamam fazlası ve birazda eksiği var. Hazır kod arşivimden. Muhtemelen Çetin üstadın kodu. Emin değilim.
--------------------------------------------------------------
* Çetin Başöz Code :
? GetTree('c:\Program Files')
SELECT CAST(filepath as c(250)) as filepath FROM folderlist
Function GetTree
Lparameters tcStartDir
Create Cursor folderlist (filepath m)
oFiler = Createobject('filer.fileutil')
With oFiler
.SearchPath = m.tcStartDir
.Subfolder = .T.
.FileExpression = '.'
.Find(0)
For ix=1 To .Files.Count
With .Files(ix)
If Bittest(.Attr,4)
Insert Into folderlist ;
(filepath) values (.Path)
Endif
Endwith
Endfor
Return .Files.Count
Endwith
--------------------------------------------------------------
Yada başka bir versiyonu :
? GetTree('C:\Program Files\Microsoft Visual FoxPro 9','*.Prg',.T.)
locate
Brow
* Cetin Basoz code. Public.
Function GetTree
Lparameters tcStartDir,tcSkeleton,tlSubfolders
Create Cursor filelist ;
(filepath m, filename c(50), ;
filesize i, fattr c(8), createtime T, lastacc T, lastwrite T)
oFiler = Createobject('filer.fileutil')
With oFiler
.SearchPath = tcStartDir
.Subfolder = tlSubfolders
.SortBy = 5
.SortDirection = 1
.FileExpression = tcSkeleton
.Find(0)
For ix=1 To .Files.Count
With .Files(ix)
If !(Bittest(.Attr,4) And .Name = '.')
Insert Into filelist ;
(filepath, filename, filesize, fattr, createtime, lastacc, lastwrite) ;
values ;
(.Path, .Name, .Size, Attr2Char(.Attr), ;
Num2Time(.Datetime), Num2Time(.LastAccessTime), Num2Time(.LastWriteTime))
Endif
Endwith
Endfor
Return .Files.Count
Endwith
Function Num2Time
Lparameters tnFloat
Return Dtot({^1899/12/30}+Int(m.tnFloat))+86400*(m.tnFloat-Int(m.tnFloat))
Function Attr2Char
Lparameters tnAttr
Return ;
IIF(Bittest(tnAttr,0),'RO','RW')+;
IIF(Bittest(tnAttr,1),'H','_')+;
IIF(Bittest(tnAttr,2),'S','_')+;
IIF(Bittest(tnAttr,4),'D','_')+;
IIF(Bittest(tnAttr,5),'A','_')+;
IIF(Bittest(tnAttr,6),'E','_')+;
? GetTree('C:\Program Files\Microsoft Visual FoxPro 9','*.Prg',.T.)
locate
Brow
Function GetTree
Lparameters tcStartDir,tcSkeleton,tlSubfolders
Create Cursor filelist ;
(filepath m, filename c(50), ;
filesize i, fattr c(8), createtime T, lastacc T, lastwrite T)
oFiler = Createobject('filer.fileutil')
With oFiler
.SearchPath = tcStartDir
.Subfolder = tlSubfolders
.SortBy = 5
.SortDirection = 1
.FileExpression = tcSkeleton
.Find(0)
For ix=1 To .Files.Count
With .Files(ix)
If !(Bittest(.Attr,4) And .Name = '.')
Insert Into filelist ;
(filepath, filename, filesize, fattr, createtime, lastacc, lastwrite) ;
values ;
(.Path, .Name, .Size, Attr2Char(.Attr), ;
Num2Time(.Datetime), Num2Time(.LastAccessTime), Num2Time(.LastWriteTime))
Endif
Endwith
Endfor
Return .Files.Count
Endwith
Function Num2Time
Lparameters tnFloat
Return Dtot({^1899/12/30}+Int(m.tnFloat))+86400*(m.tnFloat-Int(m.tnFloat))
Function Attr2Char
Lparameters tnAttr
Return ;
IIF(Bittest(tnAttr,0),'RO','RW')+;
IIF(Bittest(tnAttr,1),'H','_')+;
IIF(Bittest(tnAttr,2),'S','_')+;
IIF(Bittest(tnAttr,4),'D','_')+;
IIF(Bittest(tnAttr,5),'A','_')+;
IIF(Bittest(tnAttr,6),'E','_')+;
IIF(Bittest(tnAttr,7),'N','_')? GetTree('C:\Program Files\Microsoft Visual FoxPro 9','*.Prg',.T.)
locate
Brow
Function GetTree
Lparameters tcStartDir,tcSkeleton,tlSubfolders
Create Cursor filelist ;
(filepath m, filename c(50), ;
filesize i, fattr c(8), createtime T, lastacc T, lastwrite T)
oFiler = Createobject('filer.fileutil')
With oFiler
.SearchPath = tcStartDir
.Subfolder = tlSubfolders
.SortBy = 5
.SortDirection = 1
.FileExpression = tcSkeleton
.Find(0)
For ix=1 To .Files.Count
With .Files(ix)
If !(Bittest(.Attr,4) And .Name = '.')
Insert Into filelist ;
(filepath, filename, filesize, fattr, createtime, lastacc, lastwrite) ;
values ;
(.Path, .Name, .Size, Attr2Char(.Attr), ;
Num2Time(.Datetime), Num2Time(.LastAccessTime), Num2Time(.LastWriteTime))
Endif
Endwith
Endfor
Return .Files.Count
Endwith
Function Num2Time
Lparameters tnFloat
Return Dtot({^1899/12/30}+Int(m.tnFloat))+86400*(m.tnFloat-Int(m.tnFloat))
Function Attr2Char
Lparameters tnAttr
Return ;
IIF(Bittest(tnAttr,0),'RO','RW')+;
IIF(Bittest(tnAttr,1),'H','_')+;
IIF(Bittest(tnAttr,2),'S','_')+;
IIF(Bittest(tnAttr,4),'D','_')+;
IIF(Bittest(tnAttr,5),'A','_')+;
IIF(Bittest(tnAttr,6),'E','_')+;
IIF(Bittest(tnAttr,7),'N','_')
-------------------------------------------------------------------------------------------
Başka bir linq sorgusu.
from p in Products
where p.OrderDetails.Any( od => od.Order.Customer.Country == "Argentina" )
select p
-------------------------------------------------------------------------------------------
Birde şu kadarcık kodun arka planda yaptığına bakın:
-------------------------------------------------------------------------------------------
-- Region Parameters
DECLARE @p0 NVarChar(9) = 'Argentina'
-- EndRegion
SELECT
[t0].[ProductID],
[t0].[ProductName],
[t0].[SupplierID],
[t0].[CategoryID],
[t0].[QuantityPerUnit],
[t0].[UnitPrice],
[t0].[UnitsInStock],
[t0].[UnitsOnOrder],
[t0].[ReorderLevel],
[t0].[Discontinued]
FROM [Products] AS [t0]
WHERE EXISTS(
SELECT
NULL AS [EMPTY] // Bu satırı okuyamadım. Onun dışındakiler tamam ..!!! TELEFON ...
FROM [ORDER Details] AS [t1]
INNER JOIN [Orders] AS [t2] ON [t2].[OrderID] = [t1].[OrderID]
LEFT OUTER JOIN [Customers] AS [t3] ON [t3].[CustomerID] = [t2].[CustomerID]
WHERE ([t3].[Country] = @p0) AND ([t1].[ProductID] = [t0].[ProductID])
)
-----------------------------------------------------------------------------------------------------------
Birazda C#
-----------------------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using Excel = Microsoft.Office.Interop.Excel;
using Word = Microsoft.Office.Interop.Word; // consume-first ne ola ki:)
namespace ExcelAutomation1
{
class Program
{
static void Main(string[] args)
{
/// Once bir kenarda datayi getirecek sorgu
/// sonra Excel otomasyonuyla sonuc
/// from ... tipi syntax VFP'ye cok benziyor ve dun gordun
/// ama tum gucune ulasamiyor + bazi seyler de onunala olmuyor
/// ayni sey.
/// GetProcesses sonucu bir cesit liste - Liste tarzi sonucu
/// olan hersey Linq ile sorgulanabilir . ile gelenlerin
/// cogu -asagi dogru mavi ok gibi ikonlular-
/// LINQ extesion metodlari - sorguya yonelik metodlar
/// Bu lambda syntax - p bir variable gibi ve selecte gelen
/// her bir "record"u sembolik olarak tutuyor
/// ProsesAdi select ProcessName as ProsesAdi gibi
/// koymasaydik kolon kendi original adina olacakti
/// new {} ile tum alanlar yerine istedigimiz iki alani aliyoruz
/// new olmasinin nedeni aldigimiz sonucta bir obje listesi
/// createobject() yapar gibiyiz
var pList = Process.GetProcesses()
.OrderByDescending(p => p.WorkingSet64)
.Select(p => new { ProsesAdi = p.ProcessName, Hafiza = p.WorkingSet64 });
// sorgu hazir - daha calismadi kenarda duruyor
Excel.Application xl = new Microsoft.Office.Interop.Excel.Application();
Word.Application wd = new Microsoft.Office.Interop.Word.Application();
Excel.Workbook wb = xl.Workbooks.Add();
xl.Visible = true;
Excel.Worksheet sh = wb.ActiveSheet;
sh.Cells[1, 1].Value = "Proses Adi";
sh.Cells[1, 2].Value = "Memory";
int r = 2;
foreach (var i in pList)
{
sh.Cells[r, 1].Value = i.ProsesAdi;
sh.Cells[r, 2].Value = i.Hafiza;
r++;
}
// bu kadarla bir calistir. Şaka gibi iyimi Var + bu satırı tuttum
// Üstad bayıldın mı?
// hayir o arada kendi makinemden birsey ariyordum
// 1 sn ye. bunu saklayalım
// sende Üstad, 5 dk ya dönüyorum . şakamı
Excel.Chart ch = wb.Charts.Add();
ch.SetSourceData(sh.UsedRange);
ch.ChartArea.Copy();
Word.Document doc = wd.Documents.Add();
wd.Visible = true;
doc.Content.Paste();
}
}
}
---------------------------------------------------------------------------------------------
İşte bu an benim bittiğim andır. Kodun yazılmasındaki intellisense özelliklerini bir görün ve ne kadar sürede bittiğini görün. Excel için external object kullanmak gerekiyor, VS da office entegrasyonu tam. Sadece References penceresinde COM object olarak Microsoft. Office Interop Excel seçmek yetiyor.
Gerçekten tarifi yok. Kesinlikle görmek lazım. İnanılmaz hızlı uygulama yazılıyor ve kodun okunaklılığı mükemmel .
Bir örnek daha :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Excel = Microsoft.Office.Interop.Excel;
namespace ExcelAutomation2
{
class Program
{
static void Main(string[] args)
{
Excel.Application x = new Excel.Application();
x.Workbooks.Add();
x.Visible = true;
Excel.Worksheet sheet = x.ActiveWorkbook.ActiveSheet;
Excel.Range range = sheet.get_Range("A1");
string sql = "select * from AdventureWorks.HumanResources.Employee";
sheet.QueryTables.Add(
@"OleDb;Provider=SQLNCLI10.1;Data Source=.\SQLserver2008;Trusted_connection=yes",
range,
sql).Refresh();
}
}
}
----------------------------------------------------------------------------------------------------------------
Ve şu kadarcık kodla: SQL Server 'a bağlandık; Datayı çektik ve Excel e aktardık. Daha ne diyim. Üstelik intellicense yine inanılmaz harika:
VS2010 + SQL Server + Excel + Word + LinqPAd, sınırların sonu yok. Bu platformlar ile hem uygulama geliştirme hızı, hemde sonuca yönelik üretkenlik inanılmaz.
VFP deki benzer örnekler sitede bolca mevcut artık buraya yapıştırmıyorum.
----------------------------------------------------------------------------------------------------------------
Arkadaşlar; sözün kısası.
Başkası Foxproyu .NET 'e karşı eleştirse, gözünün üstünde kaşın var deyip, eklımdan geçeni dudaklarıma dökerim; ama bunu Çetin üstad söyleyince işin şekli değişiyor. Bu bir!!! İkincisi ben burada ne kadar yazarsam yazayım; uygulamalı olarak görmek lazım. .NET VS 2010 ile gerçekten aşmış durumda. SQL Server + VS + LinqPAD + Excel + Word ile hayallerin gerçekten sınırı yok.
Ben kendi adıma fazla bencil olamadım ve bunları sizlerle paylaşmanın doğru olacağına inandım. Gerisi artık bizlerin isteğine ve Çetin Üstad 'ın görüşüne kalmış....
Bir kaç ekstra not: WPF + Xaml ve Excel + Word entegrasyonuna hiç girmedim. Ayrıca Çetin Üstad VS 2010 platformunda; 1 milyar kaydı SQL Server dan çekip, excel 'e atmanın 1sn yeden kısa süreceğini söylediğinde yüz halimi düşünmeyin. ( Doğru okunuz tam 1 ve 9 tane 0 kayıt ve 1 sn. ye altında bir süre.)
Üstad, ben kendi adıma ( eğer düşünüyorsan ve olucaksa ), yeni teknolojileri senden öğrenmeyi iple çekiyorum.
Dilerim diğer arkadaşlardan olumlu eleştiriler alırım...
Uğur YILMAZ.
-------------------------------------------------------------------------------------------------------------
Hayat bir bisiklete binmek gibidir. Pedalı çevirmeye devam ettiğiniz sürece düşmezsiniz. Claude Peppeer
Kusuru söylenmeyen adam, ayıbını hüner sanır. Türk Atasözü