# WPF للرجل على شبكة الإنترنت…قصة عن الألم, اليأس والتعلم

<datetime class="hidden">2010-08-16T00:00</datetime>

<!-- category -- mostlylucidcouk, Imported -->
حسناً , حسناَ أنا ’ أبالغ في dramatizing it a bit :) كما قد لاحظتم من أعمالي [آخر投稿](http://mostlylucid.net/archive/2010/01/07/1331.aspx) لقد بدأت العمل على بعض الاشياء التي خارج منطقة الراحة الخاصة بي [كوزودوكان](http://blog.cozwecan.com),عمل لشخص يدعى [@RobertTheGrey](http://twitter.com/robertthegrey)"مسك0" المشروع الأول الذي نعمل عليه "مسک1" هو موقع بيع الصور "مكس2" تعرفون نوعاً ما مثل "Getty Images" "مسكو3" "Smugmug" / "Flickr" باستثناء المصور المباشر" "المسكو5" "بيعات الزبائن" [مطور بدوام كامل](http://blog.cozwecan.com/2010/01/year-and-team-members.html) (إلى الآن!) أناM SK2لقد تم توظيفي ببناء الغالبية العظمى من التطبيقات ( سواء كانت على شبكة الإنترنت ,ផ្ទៃតុMSC5 وهلم جراMST6 التي نحتاجها للقيام بالعمل

من الواضح أن واحدة من أهم النقاط في موقع التجارة الإلكترونية هي الأشياء التي يمكن بيعها. في حالتنا هذه مجموعة من الصور ذات الجودة العالية حقاً التي تم التقاطها من قبل المصورين المحترفين في جميع أنحاء العالم. السؤال الأول.

عندما كنت أعمل على المتطلبات, أصبح واضحاً بسرعة أن هذا يجب أن يكون تطبيق مكتبي, كان يتوجب عليه أن يسمح بالتشغيل على كاميرات متعددةMSC2megabytesM SK3 يتوجوب عليه أن يُسمح |‘ |إسماء | ’ | Offline |ـ. | خصوصاً خلال التحميل الأولي ٬, | هنالك |МSK8 | |M10-100 | الآلاف من الصور التي يتم العمل عليها ٬ … | إجبار هذا على أن يكون على الإنترنت يضيف تأخيراً مؤسفاً ويجعل المهمة ألماً في المؤخرة لإنهاءها |  
الآن , في رأسي الخاص بهذا الأمر أدى إلى عدد من القرارات حول الخصائص التي تحتاجها التطبيق للدعم

1. الواجهة البديهية..,..الواجهة المتفاعلة.. ;..المستخدمين ليسوا بالضرورة حاسبين.
2. تحتاج إلى القيام ببعض معالجة الصور عن بعد ; نحن ’ نحن نخطط لتشغيل هذا على السحاب | …. | CPU الوقت يكلف أموال نقدية
3. يجب أن تعمل خارج نطاق الإنترنت
4. يتوجب علينا أن نبني حول تحميل قابل للثقة للعديد من الملفات -موجات (و على امتداد نطاقات الاتصال المحتملة الصغيرة

إذن , هذه هي الإحتياجات الأساسية … تقنياً يقودني هذا إلى بعض الخيارات التكنولوجية

1. متعددة-لقراءة /التطابقة (مثل أي تطبيق مكتبي حقيقيM SK3 هو المفتاحMSC4مثل تقنية مكتبية لائقةMST5
2. أنظروا إلى الأعلى, نحن بحاجة إلى ‘مراقبةM SK2 لإيجاد الملفات الجديدة التي تصل إلينا
3. إذن , يحتاج إلى نوع من الثبات … بالإضافة إلى متطلبات تطبيقات أساسية أخرى - مSK3e.gM SK5 نُسمّي |) سنحتاج إلى القليل | , | DB خفيف
4. تحتاج ‘block’ تحميلات مبنية على إعادة المحاولة / تتحقق من المعروضات التي تم تحميلها

لحسن الحظ، أنا ’ أعمل كمطورة لفترة طويلة وكان لدي على الأقل فكرة عن المكان الذي يجب أن أبدأ فيه… سيكون التحدي الأكبر هو التعلم  
أولاً , المنصة المعتادة على المكتب اليوم هي WPF … هذا في جوهرها استبدال الحالي لـ WinForms [الكتب](http://www.amazon.co.uk/Pro-WPF-2008-Presentation-Foundation/dp/1590599551/ref=sr_1_1?ie=UTF8&s=books&qid=1264019165&sr=8-1) على [WPF](http://www.amazon.co.uk/WPF-Action-Visual-Studio-2008/dp/1933988223/ref=sr_1_1?ie=UTF8&s=books&qid=1264019184&sr=8-1), تابعت كل محادثات الـ PDC, المدونات الموسيقية وغيرهمMSC2 حول الموضوعM SK3 بعد 3 أسابيع أنا ’ أشعر أخيراً بالراحة مع الأمر  
ثانيا, أحتاج إلى DB… يتوجب علي أن يكون وزنه خفيف , يُتوجب على دعم LINQ MSC3 ماM SK4 أحب LIN Q :)), يَتوجب عليه دعم نوع من تكنولوجيا ORM  
كان الخيار الأكثر وضوحا [إصدار SQL Server Compact](http://www.microsoft.com/Sqlserver/2008/en/us/compact.aspx), نوع من сервер SQL المقطع الذي هو عظيم لتطبيقات डेस्कटॉप …لكن…لم أستطع جعله يعملM SK3 تبين أنهMSC4 حساس حقاً لإصدارات مختلفة من المكونات المركبةMST5 كان هذا ضوءاً أحمراً بالنسبة لي MST6 احتجت إلى أن يكون DB مستقيماًM ST7 وحيداً قدر الإمكانM st8 لقد تركت خيار واحد واضح M st9  
SQLite, من الموقع

‘SQLite عبارة عن مكتبة برمجية تقوم بتطبيق [بذاته-أحتوي](http://www.sqlite.org/selfcontained.html), [بدون حاسوب](http://www.sqlite.org/serverless.html), [صفر-configuration](http://www.sqlite.org/zeroconf.html), [عملية](http://www.sqlite.org/transactional.html) محرك قاعدة بيانات SQL. SQLite هو [تم نشرها بشكل واسع](http://www.sqlite.org/mostdeployed.html) محرك قاعدة بيانات SQL في العالم. الرمز المصدر لSQLite موجود في [المجال العام](http://www.sqlite.org/copyright.html).’

مثالي! لـ . دعم شبكة الإنترنت , استخدمت [مقدم SQLite ADO.NET](http://sqlite.phxsoftware.com/) ( هناك [C# فقط واجهة SQLite](http://code.google.com/p/csharp-sqlite/), لكنها ’ أبطأ وليست ضرورية في سيناريوي

إختياراتي لـ ORM كانت [تظل في فراغ](https://www.hibernate.org/343.html) أو EF…بوجود دعم لSQLite في كلا من هذه المنصات  
الآن, لقد استخدمت nHibernate لـ [المشروع الأخير](http://www.trainyourbusinessbrain.com/business-brain-training/) ( "disclaimer" , لقد غادرت مبكراً جداً في المشروع :)) وأحد الأشياء التي تسببت في إزعاجي كان عدد كبير من الإعتمادات , والضعف الذي يبدو في جميع نسخ هذه الإعتباطات "  
هذا left me with one choice…[إطار Entity](http://en.wikipedia.org/wiki/ADO.NET_Entity_Framework). الآن , لم يكن هذا ,’ خيار سهل .… لقد استخدمت EF في الماضي . [أدى إلى هذا](http://efvote.wufoo.com/forms/ado-net-entity-framework-vote-of-no-confidence/)). الآنM SK1 أنا’ لا أدخل في السياسة وراء اختيار الـMS لدفع الـEF ( ونعمMSC4 كان ذلك خياراً سياسياًMST5 لكن VMSR6 مضطرب إلى حد ماM st7 وبالنسبة لي على الأقل غير طبيعياً إلى حدٍ ما MST8 هذا قادني إلى ثاني دراستي m st9 الفرصMst10 الإطار الأساسي للكياناتMstrk11 كما أكتب هذا م st12 إنه م st13 حرفياً الم st14 ساعات منذ أن قمت باكتشاف آخر جزء من الألم الـ EF ام st15 الذي أدى إلى هذا النموذج ام st16

[![التقاط](Capture_thumb_3C08CB45.jpg "Capture")](http://www.mostlylucid.net/Images/WPFfortheWebguyastoryofpaindespairandlea_126C4/Capture.jpg)

يبدو الأمر بسيطاً …حسناً,نعمM SK2لكن هذا ’ أخذني وقتاً طويلاً للوصول إلى هذا النموذج …أعرف SQL جيداً حقاً،, CMSC6 جيد جداً، , لكن المزيج من المبادئ الغامضة،, و poor documentation and obfuscated error messages makes working | / | learning EF way too hard | ! | EF |4 | | МSK12 | في VS | مَسْكْكِكْيْكَيْکْيَكْرْكـيْمْكّيْنْه |

لذا , أن ’ عملت … آمل :)

إذن , لقد ذكرت سابقاً أن SQLite لديه مشكلة صغيرة … إنه لا يحس بـ ’ حقاً بالمقارنة

```
public static void AddRange(IEnumerable<UploadFile> files)
        {
            using (PixEntities ent = new PixEntities())
            {
                using (new ReadLock(entityLock))
                {

                    using (new WriteLock(entityLock))
                    {
                        foreach (var file in files)
                        {
                            ent.AddToUploadFiles(file);
                            ent.SaveChanges();
                        }
                    }
                }
            }
        }
```

```
 
```

كما رأيتم , هذا يحتوي على عناصر رئيسية … أستخدم حاسوب القراءة ( حيث يمكنني أن أقرأ عادة \*من\* الDB, في هذه الحالة اممM SK2 أنا لا أستخدم ’t :) عندها أستخدم WriteLock لتغليف أي عملية أكتب فيها إلى DBMSC5 سيلاحظ المراقب أيضاً ما يبدو وكأنه خطأMスク6 أنا أفعل entMske7SaveChagesMska8 لكل تكرار للدائرة

الفصل الصغير الذي أستخدمه هو من [هنا](http://dotnetcommandos.com/blogs/brianr/archive/2008/09/26/thread-safe-dictionary-in-net.aspx), لكني ’ وضعتها في الأسفل من أجل إستخدامكم… على أي حالM SK3 هذا جزء واحد من عدة أجزاء من تجاربي في العمل على [كوزودوكان](http://blog.cozwecan.com)…أبقى مضبطا!

```
  public static class Locks
    {
        public static void GetReadLock(ReaderWriterLockSlim locks)
        {
            bool lockAcquired = false;
            while (!lockAcquired)
                lockAcquired = locks.TryEnterUpgradeableReadLock(1);
        }

        public static void GetReadOnlyLock(ReaderWriterLockSlim locks)
        {
            bool lockAcquired = false;
            while (!lockAcquired)
                lockAcquired = locks.TryEnterReadLock(1);
        }

        public static void GetWriteLock(ReaderWriterLockSlim locks)
        {
            bool lockAcquired = false;
            while (!lockAcquired)
                lockAcquired = locks.TryEnterWriteLock(1);
        }

        public static void ReleaseReadOnlyLock(ReaderWriterLockSlim locks)
        {
            if (locks.IsReadLockHeld)
                locks.ExitReadLock();
        }

        public static void ReleaseReadLock(ReaderWriterLockSlim locks)
        {
            if (locks.IsUpgradeableReadLockHeld)
                locks.ExitUpgradeableReadLock();
        }

        public static void ReleaseWriteLock(ReaderWriterLockSlim locks)
        {
            if (locks.IsWriteLockHeld)
                locks.ExitWriteLock();
        }

        public static void ReleaseLock(ReaderWriterLockSlim locks)
        {
            ReleaseWriteLock(locks);
            ReleaseReadLock(locks);
            ReleaseReadOnlyLock(locks);
        }

        public static ReaderWriterLockSlim GetLockInstance()
        {
            return GetLockInstance(LockRecursionPolicy.SupportsRecursion);
        }

        public static ReaderWriterLockSlim GetLockInstance(LockRecursionPolicy recursionPolicy)
        {
            return new ReaderWriterLockSlim(recursionPolicy);
        }
    }

    public abstract class BaseLock : IDisposable
    {
        protected ReaderWriterLockSlim _Locks;

        public BaseLock(ReaderWriterLockSlim locks)
        {
            _Locks = locks;
        }

        public abstract void Dispose();
    }

    public class ReadLock : BaseLock
    {
        public ReadLock(ReaderWriterLockSlim locks)
            : base(locks)
        {
            Locks.GetReadLock(this._Locks);
        }

        public override void Dispose()
        {
            Locks.ReleaseReadLock(this._Locks);
        }
    }

    public class ReadOnlyLock : BaseLock
    {
        public ReadOnlyLock(ReaderWriterLockSlim locks)
            : base(locks)
        {
            Locks.GetReadOnlyLock(this._Locks);
        }

        public override void Dispose()
        {
            Locks.ReleaseReadOnlyLock(this._Locks);
        }
    }

    public class WriteLock : BaseLock
    {
        public WriteLock(ReaderWriterLockSlim locks)
            : base(locks)
        {
            Locks.GetWriteLock(this._Locks);
        }

        public override void Dispose()
        {
            Locks.ReleaseWriteLock(this._Locks);
        }
    }
```