【发布时间】:2011-03-24 18:31:25
【问题描述】:
我在Dealer 之间建立了一对多的关系,而Cars 可以拥有多个Cars。
我正在尝试将用于 EF 的 C# 代码转换为 F#...问题只是在我的 F# 代码中它可以很好地获得经销商,但它不会用于那个经销商...它只是返回 null ,但是在 C# 版本中它可以工作吗?
我的代码:
C# 版本
public class Dealer
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Car> Cars { get; set; }
public Dealer()
{
Cars = new List<Car>();
}
}
public class Car
{
public int ID { get; set; }
public string CarName { get; set; }
public Dealer Dealer { get; set; }
public int DealerId { get; set; }
public Car()
{
Dealer = new Dealer();
}
}
public class MyContext : DbContext
{
public DbSet<Dealer> Dealers { get; set; }
public DbSet<Car> Cars { get; set; }
public MyContext()
{
Database.Connection.ConnectionString = "server=some;database=dbname;user id=uid;password=pwd";
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Dealer>()
.HasMany(x => x.Cars)
.WithRequired(x => x.Dealer)
.HasForeignKey(x => x.DealerId);
modelBuilder.Entity<Car>()
.HasRequired(x => x.Dealer)
.WithMany()
.HasForeignKey(x => x.DealerId);
modelBuilder.Entity<Dealer>().ToTable("Dealers");
modelBuilder.Entity<Car>().ToTable("Cars");
}
}
... 查询经销商及其汽车的 Program.cs:
static void Main(string[] args)
{
var ctx = new MyContext();
foreach (var s in ctx.Dealers.FirstOrDefault(x => x.ID == 1).Cars)
{
Console.WriteLine(s.CarName);
}
Console.Read();
}
F# 版本
type Dealer() =
let mutable id = 0
let mutable name = ""
let mutable cars = List<Car>() :> ICollection<Car>
member x.ID with get() = id and set v = id <- v
member x.Name with get() = name and set v = name <- v
abstract member Cars : ICollection<Car> with get, set
override x.Cars with get() = cars and set v = cars <- v
and Car() =
let mutable id = 0
let mutable carName = ""
let mutable dealer = Dealer()
let mutable dealerId = 0
member x.ID with get() = id and set v = id <- v
member x.CarName with get() = carName and set v = carName <- v
member x.Dealer with get() = dealer and set v = dealer <- v
member x.DealerId with get() = dealerId and set v = dealerId <- v
type MyContext() =
inherit DbContext("server=some;database=dbname;user id=uid;password=pwd")
[<DefaultValue>] val mutable dealers : DbSet<Dealer>
member x.Dealers with get() = x.dealers and set v = x.dealers <- v
[<DefaultValue>] val mutable cars : DbSet<Car>
member x.Cars with get() = x.cars and set v = x.cars <- v
override x.OnModelCreating(modelBuilder:DbModelBuilder) =
modelBuilder.Entity<Dealer>()
.HasMany(ToLinq(<@ fun ka -> ka.Cars @>))
.WithRequired(ToLinq(<@ fun sk -> sk.Dealer @>))
.HasForeignKey(ToLinq(<@ fun fg -> fg.DealerId @>)) |> ignore
modelBuilder.Entity<Car>()
.HasRequired(ToLinq(<@ fun ak -> ak.Dealer @>))
.WithMany()
.HasForeignKey(ToLinq(<@ fun ka -> ka.DealerId @>)) |> ignore
modelBuilder.Entity<Dealer>().ToTable("Dealers")
modelBuilder.Entity<Car>().ToTable("Cars")
... ToLinq 函数:
let ToLinq (exp : Expr<'a -> 'b>) =
let linq = exp.ToLinqExpression()
let call = linq :?> MethodCallExpression
let lambda = call.Arguments.[0] :?> LambdaExpression
Expression.Lambda<Func<'a, 'b>>(lambda.Body, lambda.Parameters)
... Program.fs 将获取经销商和他的汽车:
let ctx = new MyContext()
let joe = ctx.Dealers.Find(1)
joe.Cars |> Seq.iter(fun x -> printfn "%s" x.CarName)
printfn "DONE"
感谢任何帮助!
【问题讨论】:
-
我对 EF 一无所知,但我看到在 F# 版本中
Dealer.Cars是一个虚拟属性,而在 C# 版本中它只是一个普通属性。如果你在 F# 中改变它会有什么不同吗? -
@wmeyer - 我这边的错。
Dealer.Cars在 C# 版本中也应该是虚拟的 - 唯一会改变的是集合现在将在 c# 中延迟加载,它也很好(刚刚测试过)。 -
我确信这不是一个重要的区别,但是你的 C# 没有调用 DBContext(str) 而你的 F# 版本调用了?
-
@Robert Jeppesen - 正如你所说,这不是一个重要的区别。我在 C# 版本中不调用
DbContext(str)的原因仅仅是它不能。我还尝试以与 C# 版本相同的方式定义 connectionString,结果相同。 - 请注意,它可以毫无问题地连接到数据库并获得Dealer,当我尝试为该经销商获取汽车时首先出现问题。 -
public MyContext() : base("connstring") 应该可以工作吗?
标签: c# entity-framework f# ef-code-first entity-framework-4.1