我使用Azure Sql和Entity-Framework Code First。
我有Transaction
表。共有4种类型buy/sell
,withdrawal
,deposit
和fee
。
例如,我需要DepositCode
存款交易,但此列对其他人而言为空。此外,我需要ItemPrice
和ItemAmount
进行买入/卖出,但对于其他类型,它将为空。
示例Transaction
表
public class Transaction
{
public long Id { get; set; }
public decimal Amount { get; set; }
public int Type { get; set; }
public string DepositCode { get; set; }
public decimal? ItemPrice { get; set; }
public decimal? ItemAmount { get; set; }
public string WithdrawalIban { get; set; }
}
或
public class Transaction
{
public long Id { get; set; }
public decimal Amount { get; set; }
public int Type { get; set; }
public DepositTransaction DepositTransaction { get; set; }
public WithdrawalTransaction BuyAndSellTransaction { get; set; }
public WithdrawalTransaction WithdrawalTransaction { get;set; }
}
public class DepositTransaction
{
public long Id { get; set; }
public Transaction Transaction { get; set; }
public string DepositCode { get; set; }
}
public class WithdrawalTransaction
{
public long Id { get; set; }
public Transaction Transaction { get; set; }
public string WithdrawalIban { get; set; }
}
public class BuySellTransaction
{
public long Id { get; set; }
public Transaction Transaction { get; set; }
public decimal ItemPrice { get; set; }
public decimal ItemAmount { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<WithdrawalTransaction>()
.HasRequired(wt => wt.Transaction)
.WithOptional(tr => tr.WithdrawalTransaction);
modelBuilder.Entity<DepositTransaction>()
.HasRequired(db => db.Transaction)
.WithOptional(tr=> tr.DepositTransaction);
modelBuilder.Entity<BuySellTransaction>()
.HasRequired(bs => bs.Transaction)
.WithOptional(tr => tr.BuySellTransaction);
}
哪一个应该首选?
答案 0 :(得分:1)
我尽可能使用可空字段,这是表中每个类层次结构映射的实现。使用这种方法,EF会将所有事务对象存储在一个表中,并使用一个鉴别器列来管理类型加载。那说我会按如下方式重构你的模型:
public abstract class Transaction
{
public long Id { get; set; }
public DateTime TransactionDate { get; set; }
}
public class DepositTransaction : Transaction
{
public string DepositCode { get; set; }
}
public class WithdrawalTransaction : Transaction
{
public string WithdrawalIban { get; set; }
}
public class BuySellTransaction : Transaction
{
public decimal ItemPrice { get; set; }
public decimal ItemAmount { get; set; }
}
答案 1 :(得分:1)
您实际上只有三笔交易:买入/卖出,存款/取款,费用。买入和卖出之间的区别在于买入为正,卖出为负。存款和取款也是如此。
create table Transactions(
ID bigint identity primary key,
XType char( 1 ) not null, -- 'B': buy/sell, 'D': dep/with, 'F': fee
Amount money not null,
constraint CK_Transaction_Type check( XType in( 'B', 'D', 'F' ),
constraint UQ_Transaction_Type unique( ID, XType )
);
其他表(或子表如果你想将它们视为这样)将如下所示:
create table BuySellTrans(
TransID bigint not null,
TransType char( 1 ) not null,
..., -- other info regarding purchase or sale
constraint CK_BuySellTrans_BuySellType check( TransType = 'B' )
constraint FK_BuySellTrans_Trans foreign key( TransID, TransType )
references Transactions( ID, XType )
);
至于代码,最好的方法可能是拥有子类BuySell,DepositWithdrawal和Fee的抽象超类Transaction。我还会提供一些方便的视图,巧合的是,BuySell,DepositWithdrawal和Fee。这些视图将提供Transactions表的连接数据集以及相应的子表。视图上的触发器(允许您的系统)将大大简化应用程序代码,因为每个子类只能通过视图进行查询和操作。代码甚至不需要知道数据库中的物理布局。