4

资源解释了如何Computed排除属性(仅在更新中?)。

指定属性应从更新中排除。

[Table("Invoice")]
public class InvoiceContrib
{
    [Key]
    public int InvoiceID { get; set; }
    public string Code { get; set; }
    public InvoiceKind Kind { get; set; }
    [Write(false)]
    [Computed]
    public string FakeProperty { get; set; }
}
using (var connection = My.ConnectionFactory())
{
    connection.Open();
    var invoices = connection.GetAll<InvoiceContrib>().ToList();
    // The FakeProperty is skipped
    invoices.ForEach(x => x.FakeProperty += "z");
    var isSuccess = connection.Update(invoices);
}

Write(false)实现同样的目的吗?[Computed]和有什么区别[Write(false)]

编辑:

我刚刚检查了针对我的问题链接的资源。它几乎击中了这一点!有人可以确认两个属性是否执行相同的操作,但只是以两种不同的方式措辞,以便为用户提供更好的抽象吗?

4

1 回答 1

9

两者都[Computed]Write(false)忽略属性 whileINSERT以及UPDATE操作。所以,两者都是一样的。您可以使用其中任何一种。

文档如下:

  • [Write(true/false)]- 这个属性是(不)可写的
  • [Computed]- 这个属性是计算出来的,不应该是更新的一部分

关于Write

如上面文档的第一行所述,Write处理“可写”行为。这应该包括INSERTUPDATE

也可以在源代码中确认:

var properties = type.GetProperties().Where(IsWriteable).ToArray();
...
...
...
private static bool IsWriteable(PropertyInfo pi)
{
    var attributes = pi.GetCustomAttributes(typeof(WriteAttribute), false).AsList();
    if (attributes.Count != 1) return true;

    var writeAttribute = (WriteAttribute)attributes[0];
    return writeAttribute.Write;
}

关于Computed

上面文档中的第二行虽然有点宽泛。

不应该是更新的一部分

这是否意味着它可以成为 的一部分INSERT?不,不是的; 它还涵盖了这两个动作。这可以通过以下代码观察到:

CREATE TABLE TestTable
(
    [ID]            [INT] IDENTITY (1,1) NOT NULL CONSTRAINT TestTable_P_KEY PRIMARY KEY,
    [Name]          [VARCHAR] (100) NOT NULL,
    [ComputedCol]   [VARCHAR] (100) NOT NULL DEFAULT '',
    [NonWriteCol]   [VARCHAR] (100) NOT NULL DEFAULT ''
)
[Table("TestTable")]
public class MyTable
{
    [Key]
    public int ID { get; set; }

    public string Name { get; set; }

    [Computed]
    public string ComputedCol { get; set; }

    [Write(false)]
    public string NonWriteCol { get; set; }
}
int id;
using(SqlConnection conn = new SqlConnection(@"connection string"))
{
    MyTable myTable = new MyTable();
    myTable.Name = "Name";
    myTable.ComputedCol = "computed";
    myTable.NonWriteCol = "writable";

    conn.Insert<MyTable>(myTable);

    id = myTable.ID;
}

using(SqlConnection conn = new SqlConnection(@"connection string"))
{
    MyTable myTable = conn.Get<MyTable>(id);
    myTable.Name = "Name_1";
    myTable.ComputedCol = "computed_1";
    myTable.NonWriteCol = "writable_1";

    conn.Update<MyTable>(myTable);
}

通过上面的代码,你会发现无论你选择哪个属性来装饰属性,它都不会被考虑 forINSERT或 for UPDATE。所以基本上,这两个属性都扮演着同样的角色。

这可以在 github 上的Dapper.Tests.Contrib测试项目中进一步确认。

[Table("Automobiles")]
public class Car
{
    public int Id { get; set; }
    public string Name { get; set; }
    [Computed]
    public string Computed { get; set; }
}
...
...
...
//insert with computed attribute that should be ignored
connection.Insert(new Car { Name = "Volvo", Computed = "this property should be ignored" });

来源:12

查看上面代码中的注释和分配给属性的值,很明显Computed应该忽略该属性进行INSERT操作;这是测试的预期结果。

为什么为同一目的提供这两种方式尚不清楚。它会引起混乱。

以下是一些额外的参考资料:

评论 1

我使用[Computed]or [Write("False")]。这不适用于您的场景吗?

评论 2

很高兴我能帮上忙。每一天都是上学日!我不确定为什么它们都存在,因为我认为它们在功能上是相同的。我倾向于使用[Computed]它只是因为它更容易打字。

评论 3

我知道使用 Dapper.Contrib 我可以使用WriteComputed属性在写入操作期间忽略属性。但是,这将忽略插入和更新的属性。我需要一种忽略更新属性的方法。我的建议是添加 2 个属性......也许命名为Insertable(bool)Updateable(bool). 当将false值传递给这些时,框架将排除给定操作的该属性。对于一个非常常见的问题,这是一种轻量级、直接的方法。

我认为Computed属性与计算列没有任何关系,因为 Dapper.Contrib 支持多个 RDBMS。

于 2019-08-27T11:44:31.537 回答