网络网友WPF 一个痛苦、绝望和学习的故事 (中文 (Chinese Simplified))

网络网友WPF 一个痛苦、绝望和学习的故事

Monday, 16 August 2010

//

2 minute read

好吧,好吧,我太过分戏剧化它了 : () 正如你可能从我身上注意到的 上一个员额 最近我加入了一家名为 哥兹韦康语Name,为名为 @RobertTheGrey @ 罗伯特·格雷我们的第一个项目是照片销售网站...你知道的有点像Getty images/Smugmug/Flickr, 除了直接的摄影师-客户销售之外。作为唯一的图片销售网站。 全职开发者 我的任务就是建立绝大多数的应用程序(无论是网络、桌面等),

电子商业网站最关键的部分之一显然是要卖的东西。 在我们的例子中,这是世界各地专业摄影师拍摄的非常高质量的照片。 第一个问题:我们如何在网站上获取这些图像,以及我们如何让摄影师在照片上添加信息,让那些想买他们的人找到这些照片? 嗯,这是我第一个被要求解决的问题!

制定要求时,很快发现这必须是一个桌面应用程序,它需要允许多兆字节照片的操作,而多兆字节照片的操作需要允许“窃听 ” 离线。 特别是在初始装货过程中,有10,100万张图像正在制作...强制在线,这增加了一个令人讨厌的滞后,使任务在屁股上变得痛苦。 最重要的是,它需要可靠!
现在,在我的Dev头部,这导致 一系列决定 关于这些功能的应用程序需要支持:

  1. 直觉的、反应灵敏的UI;用户不一定是计算机保存的,需要使用明显的UI隐喻,使其速度足够快,便于使用。
  2. 需要做一些离线图像处理; 我们正计划在云上托管这个...。 CPU时间成本为现金: )
  3. 应在离线下工作
  4. 需要围绕可靠的多兆格文件上传(跨潜在小连接带宽)来构建。

这些是基本需求 从技术上讲,这让我找到一些技术选择:

  1. 多行/共通货币(与任何真正的桌面应用程序一样)是关键就像一个体面的桌面技术
  2. 我们需要“观察”新文件抵达, 使缩略图透明,
  3. 所以,它需要某种持久性... 加上其他的非核心部分需求(例如标记), 我们可能需要一点点,轻量级的DB。
  4. 需要基于“ block” 的上传并重试/ 校验上传项目

幸运的是, 我当了相当长一段时间的牧师, 至少知道从何开始, 最大的挑战就是学习!
首先,显而易见的桌面平台是WPF(WPF)......这实质上是目前WinForms(WinForms)的替代物,它非常可定制,但有一个有点臭名昭著的陡峭学习曲线。 书本 上 年 月 WPPF WPPF3周后, 我终于感到舒服了...
第二,我需要一个DB... 需要轻量级, 需要支持LINQ(什么,我喜欢LINQ:)), 需要支持某种ORM技术。
最明显的选择是 SQL 服务器压缩版SQL服务器, SQL 服务器被削减了, 这对于桌面应用程序来说是件好事... 但是... 我无法成功! 事实证明它对各种安装组件的版本非常敏感 。 这对我来说是一个红灯... 我需要 DB尽可能独立! 这留下了一个显而易见的选择 :
SQLite,来自网站:

SQLite(SQLite)是一个软件库, 自足自足, 无服务器, 零配置, 交易交易 SQL 数据库引擎。 SQLite 是 部署最广泛 SQL 世界上 SQL 数据库引擎。 SQLite 的源代码在 公共领域.’

完美! SQLite ADO.NET 提供商 (有一个 C # 只有SQLite 端口部署实际上包括一个参考和创建一个文件。 现在它确实有一个非常严格的限制, 我稍后会覆盖这个限制。 )

我的ORM选择 怀内 或EF... 支持SQLite 在这两个平台。
现在,我用了NHHEVERTA 最近的项目 (否认,我在项目中提前离开了 : ) , 令我恼怒的一件事是大量依赖关系,以及这些依赖关系的不同版本之间看起来的脆弱性。 对于一个低影响桌面应用程序来说,这只是一个太大的足迹和太大的风险。 因此我不得不把它计数出来。
这给我留下了一个选择实体框架. 现在,这不是一个容易的选择.我过去曾经使用EF(与EF有关),发现这是一个痛苦的经历.(其他人也有这种经历)。 导致此结果现在,我并不是在MS选择推行EF(而且,是的,这是一个政治选择)的背后进入政治,但是V1是相当古怪的,至少对我来说是相当非自然的。 这导致我第二次学习“机会 ” 。 “Master实体框架 ” 。 在我写这封信的时候,我花了2小时的时间才完成我最后一点EF的痛苦...这导致了这个模型:

捕获

我对SQL非常了解, C#也非常清楚, 但模糊的概念、文件简陋、错误讯息混杂, 效果/学习EF太难! EF 4 (在 VS 2010/.NET 4 中) 改进了这一点,

我希望:)

因此,我先前曾提到,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, 在此情况下 umm, I don't : () ) 之后, 我用一个 WriterLock 来包扎我写给 DB 的任何操作。 观察者也会注意到什么看起来像一个错误... I do ent. savechages () 对于循环的每次迭代... 这是另一个 SQLite 奇克, 它不支持批次更新... 如果您尝试的话, 它会给文件锁出一个奇怪的错误 :

我用的小锁舱是来自 在这里但我把它放在下面供你使用 哥兹韦康语Name保持监听!

  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);
        }
    }
Finding related posts...
logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.