ServiceStack OrmLite 如何实现外键/相关属性的自动设置?

2024-01-12

我创建了以下示例来测试外键,到目前为止,它运行良好。我希望能够做的是使用我构建的这个框架来设置关系的属性,并让它在保存父级时保存子对象并自动设置主键和外键。 DataManager 类公开 Connection

 public class DataManager
{

    DataManager()
    {
        OrmLiteConfig.DialectProvider = SqliteDialect.Provider;
        ConnectionString = SqliteFileDb;
        updateTables();
    }

    private void updateTables()
    {
        using (var dbConn = OpenDbConnection())
        {
            dbConn.DropAndCreateTable<Person>();
            dbConn.DropAndCreateTable<PhoneNumber>();
        }
    }
    public static string SqliteFileDb = "~/App_Data/db.sqlite".MapAbsolutePath();
    private static DataManager manager;
    public static DataManager Manager {

        get
        {
            if (manager == null)
                manager = new DataManager();
            return manager;
        }
    }
    public IDbConnection InMemoryDbConnection { get; set; }
    public IDbConnection OpenDbConnection(string connString = null)
    {
        connString = ConnectionString;
        return connString.OpenDbConnection();
    }
    protected virtual string ConnectionString { get; set; }
    protected virtual string GetFileConnectionString()
    {
        var connectionString = SqliteFileDb;
        return connectionString;
    }
}

这些是我的 POCO 以及用于实现我的结果的 BaseClass:

    public class Person : LiteBase
{
    [AutoIncrement]
    [PrimaryKey]
    public int Id { get; set; }

    public string Name { get; set; }
    public string Surname { get; set; }
    private List<PhoneNumber> numbers;
    public List<PhoneNumber> PhoneNumbers {
        get
        {
            if (numbers == null)
                numbers = GetList<PhoneNumber>(p => p.Person == Id);
            return numbers;
        }
    }

}

public class PhoneNumber
{
    public string Number { get; set; }
    public string Description { get; set; }

    [AutoIncrement]
    [PrimaryKey]
    public int Id { get; set; }

    [References(typeof (Person))]
    public int Person { get; set; }

    public void AddPerson(Person person)
    {
        Person = person.Id;
    }
}

public class LiteBase:INotifyPropertyChanged
{
    public List<T> GetList<T>(Expression< Func<T,bool>> thefunction) where T : new()
    {
        var objects = new List<T>();
        using (var conn = Data.DataManager.Manager.OpenDbConnection())
        {
            objects = conn.Where<T>(thefunction);
        }
        return objects;
    }

    public T GetItem<T>(Expression<Func<T, bool>> thefunction) where T : new()
    {
        T obj = new T();
        using (var conn = Data.DataManager.Manager.OpenDbConnection())
        {
            obj = conn.Where<T>(thefunction).FirstOrDefault<T>();
        }
        return obj;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) 
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

创建 Person 和 PhoneNumber 对象的简单类

 public class PersonManager
    {

        public void CreatePerson(string name, string surname, string number)
        {
            using (var conn = DataManager.Manager.OpenDbConnection())
            {
                var pnum = new PhoneNumber { Number = number };
                var person = new Person
                    {
                        Name=name,
                        Surname = surname,

                    };
                conn.Save<Person>(person);
                var id = conn.GetLastInsertId();
                person.Id = (int)id;
                pnum.AddPerson(person);
                conn.Save<PhoneNumber>(pnum);

            }
        }

        public List<Person> GetPeople()
        {
            List<Person> people;
            using (var conn = DataManager.Manager.OpenDbConnection())
            {
                people = conn.Select<Person>();
            }
            return people;
        }

        public List<PhoneNumber> GetNumbers()
        {
            List<PhoneNumber> numbers;
            using (var conn = DataManager.Manager.OpenDbConnection())
            {
                numbers = conn.Select<PhoneNumber>();
            }
            return numbers;
        }
    }

这是用法:

var manager = new PersonManager();
        manager.CreatePerson("John", "Doe", "12345679");
        manager.CreatePerson("Jack", "Smith", "12345679");
        manager.CreatePerson("Peter", "Jones", "12345679");
        manager.CreatePerson("Dan", "Hardy", "12345679");
        var people = manager.GetPeople();
        var numbers = manager.GetNumbers();
        for (int i = 0; i < people.Count; i++)
        {
            Console.WriteLine("{0} {1} {2}",
                people[i].Name,people[i].Surname,people[i].Id);
        }
        for (int n = 0; n < numbers.Count; n++)
        {
            Console.WriteLine("PN: {0} {1}",
                numbers[n].Number,numbers[n].Person);
        }
        for (int p = 0; p < people.Count; p++)
        {
            var person = people[p];
            Console.WriteLine("{0}: {1} {2} {3}",
                person.Id,person.Name,person.Surname,person.GetItem<PhoneNumber>(x=>x.Person==person.Id).Number);
        }

输出如我所料:

无名氏 1

杰克·史密斯 2

彼得·琼斯 3

丹·哈迪 4

编号:12345679 1

编号:12345679 2

号码:12345679 3

号码:12345679 4

1:约翰·多伊 12345679

2:杰克·史密斯 12345679

3:彼得·琼斯12345679

4:丹·哈迪 12345679

我真正希望能够做的是以下事情:

var john = new Person
                {
                    Name = "John",
                    Surname = "Smith",
                    PhoneNumber = new PhoneNumber { Number = "123456789" }
                };
                conn.Save<Person>(john);
                var number = john.PhoneNumber.Number

这是可能吗?


默认情况下,OrmLite v3 将所有复杂类型属性存储在字符串字段中,您需要显式设置所有引用。

在下一个主要 v4 版本中(预计 2013 年 11 月下旬),OrmLite添加了对外部引用的一些支持 https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/tests/ServiceStack.OrmLite.Tests/LoadReferencesTests.cs#L80[Reference]属性,它可以让您告诉 OrmLite 这些属性应该存储在外部表中而不是 blob,例如:

public class Customer
{
    [AutoIncrement]
    public int Id { get; set; }
    public string Name { get; set; }

    [Reference]
    public CustomerAddress PrimaryAddress { get; set; }

    [Reference]
    public List<Order> Orders { get; set; }
}

这将允许您致电db.SaveReferences()保存参考属性,例如:

var customer = new Customer
{
    Name = "Customer 1",
    PrimaryAddress = new CustomerAddress {
        AddressLine1 = "1 Humpty Street",
        City = "Humpty Doo",
        State = "Northern Territory",
        Country = "Australia"
    },
    Orders = new[] { 
        new Order { LineItem = "Line 1", Qty = 1, Cost = 1.99m },
        new Order { LineItem = "Line 2", Qty = 2, Cost = 2.99m },
    }.ToList(),
};

Assert.That(customer.Id, Is.EqualTo(0)); //Id is not saved yet

//Inserts customer, populates auto-incrementing customer.Id
//Specify `references:true` to populate the ForeignKey ids and 
//save the related rows as well, e.g:
db.Save(customer, references:true); 

Assert.That(customer.Id, Is.GreaterThan(0)); 
Assert.That(customer.PrimaryAddress.CustomerId, Is.EqualTo(customer.Id));
Assert.That(customer.Orders.All(x => x.CustomerId == customer.Id));

手动保存参考文献

为了进行更细粒度的控制,您还可以选择要保存的引用,例如:

db.Save(customer);  //Doesn't save related rows

//1:1 PrimaryAddress Reference not saved yet
Assert.That(customer.PrimaryAddress.CustomerId, Is.EqualTo(0));

//1:1 PrimaryAddress Reference saved and ForeignKey id populated
db.SaveReferences(customer, customer.PrimaryAddress);

//1:Many Orders References saved and ForeignKey ids populated
db.SaveReferences(customer, customer.Orders);

加载与实体相关的所有行

然后,您可以加载主行及其所有引用db.LoadSingleById, e.g:

var dbCustomer = db.LoadSingleById<Customer>(customer.Id);

dbCustomer.PrintDump();

Assert.That(dbCustomer.PrimaryAddress, Is.Not.Null);
Assert.That(dbCustomer.Orders.Count, Is.EqualTo(2));
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ServiceStack OrmLite 如何实现外键/相关属性的自动设置? 的相关文章

  • ServiceStack 基准测试继续:为什么将简单(复杂)持久化为 JSON 会减慢 SELECT 速度?

    我想切换到 OrmLite 我需要弄清楚它是否很慢 如果是 原因是什么 在我的研究中 我得出的结论是 复杂的对象 在 OrmLite 中被 blob 为 JSON 是 SELECT 速度非常慢的罪魁祸首 因此 我创建了一个仅关注 OrmLi
  • Razor.ServiceStack - 视图不渲染,只是默认的“快照”

    我已经使用设置了一个网站http razor servicestack net http razor servicestack net 我创建了多个视图和匹配服务 示例如下 服务示例 using ServiceStack ServiceHo
  • SQL Server 对 OrmLite 的特定类型支持

    我刚刚了解了一种天才类型 它可以简化我的很多工作 但看起来我喜欢的 ORM 无法识别它 有没有办法让 ServiceStack OrmLite 识别HierarchyId在 SQL Server 中 关于要修改哪些文件的任何建议以及如何继续
  • 检查约束中的 SQL 子查询

    我可以在 Check 约束中进行 SQL 子查询吗 I ve a post带列的表id owner我还有另一张桌子action有柱子user id post id Table user有柱子id post id gt post id and
  • SQL - 两个相互依赖的外键

    目前的结构如下 Table RowType RowTypeID Table RowSubType RowSubTypeID FK RowTypeID Table ColumnDef FK RowTypeID FK RowSubTypeID
  • 支持 CORS 的服务器发送事件

    我在用ServiceStack 中的服务器发送事件 https github com ServiceStack ServiceStack wiki Server Events我需要允许它跨来源使用 我已经设置了ServiceStackCor
  • 如何对ServiceStack进行单元测试?

    我喜欢 SS 但我在尝试对我的业务层进行单元测试时摸不着头脑 我是单元测试和模拟的新手 并且一直在阅读 NSubstitute 因为这看起来像是一个有趣的模拟层 我的文件结构大致如下 MainAppHostProject AppStart
  • ServiceStack razor 默认页面

    假设我有 2 页 NotADefault cshtml Views Default cshtml 问题1 现在我运行它 页面A无论我如何命名它 它总是被隐式地调用为启动默认页面 Page B仅当我显式调用 localhost View De
  • XSD 中缺少响应和 DTO 对象

    我正在使用最新版本的 ServiceStack 和 NuGet 我已经有了一个基本的服务设置 可以与 JsonServiceClient 很好地配合 并且按预期通过了所有单元测试 不幸的是 我还尝试支持 SOAP 和 Visual Stud
  • 如何使用 Moq 测试 ServiceStack 服务

    我有一个使用 ServiceStack 创建的休息服务 使用 nHibernate 作为从 SqlCe 数据库获取数据的方式 我一直在尝试使用 nUnit 和 Moq 编写一些单元测试 我已成功模拟 nHibernate 实现以返回 nul
  • servicestack ormlite 中的分页

    我正在寻找一种在 ormlite 中实现分页的好方法 我发现了另一种question https stackoverflow com questions 15705419 passing params expression results
  • 当 WebRequest 无法找到该前缀的创建者时出现“NotSupportedException”

    我有一个非常奇怪的问题WebRequest in a ServiceStackWeb 应用程序 由 Mono 上的 XSP 托管 看起来请求模块的注册工作方式非常奇怪 我在用WebRequest创建一个 HTTP 请求 但它失败了 因为它无
  • ServiceStack Ormlite 和 RowVersion 支持

    在更新期间支持 sql server rowversion 的最简单方法是什么 我试过这个 db UpdateOnly u f gt new f Name f Description f Modified f ModifiedBy f gt
  • ServiceStack.DataAnnotations 缺少属性定义?

    我正在尝试使用 ServiceStack DataAnnotations 中的 ServiceStack 属性装饰器 但是当我在 MSVS 对象浏览器中查看 ServiceStack DataAnnotations 命名空间时 只有以下类型
  • ServiceStack.Text序列化循环引用

    我需要像这样序列化对象图 public class A public B Link1 get set public class B public A Link2 get set 这样json只得到两个实例 但又被正确反序列化了 例如 使用元
  • servicestack 自托管服务使用分块编码 - 是无缓冲的吗?

    我正在尝试通过 hello world 示例和自托管示例来学习 ServiceStack 我正在请求 JSON 内容 我在响应标头中注意到以下内容 ASP Net 项目中托管的基本服务 HTTP 1 1 200 OK Server ASP
  • 将架构名称与 SQL Server 和 ServiceStack.OrmLite 一起使用

    有人知道如何将正确的 Alias 属性应用于具有架构名称的查询表吗 我有一张桌子叫accounts register 我尝试过使用 Alias accounts register 作为 Register 类的类装饰器属性 但这不起作用 如果
  • 用户反馈系统的正确数据库模型(一个有趣的案例)

    我正在使用 PHP 和 Yii Framework 开发一个应用程序 我一直在考虑最适合给定功能的数据库结构 这就是我的想法 但我并不是 100 肯定应该这样做 因此我决定询问社区 应用程序说明 注册用户可以参加活动 每个事件都可以有一个
  • 主干关系有许多最佳实践

    我是 Backbone 关系新手 我不确定使用 HasMany 的正确方法是什么 我有一个Parent模型有很多children 许多 是指成千上万的孩子 为了避免性能问题 我通过外键查询子项 child parent 1 而不是创建一个巨
  • 用作 ServiceStack 的 IoC 时在 autofac 中配置生命周期范围

    我目前正在使用 AutoFac 作为我们的 ServiceStack Web 服务应用程序的 DI 容器 我能够配置接线和所有内容 但在阅读了有关范围的部分后 我不知道在注册我的组件时最好使用哪个范围 在我们的特定情况下 我认为 PerHt

随机推荐